Android Custom Control implementation

Source: Internet
Author: User

Recently wrote a custom countdown control in the project, the effect is that after the countdown begins, Hearts are gradually filled. Effects such as:


It is divided into two parts: a timer and a drawing bitmap.

Timers use the timer and TimerTask to perform a timertask run function once per second to redraw the control. The code is as follows:

Mtimer = new Timer (), mtimertask = new TimerTask () {@Overridepublic void run () {postinvalidate (); synchronized (this) {if (i Ndex >) {index = 1;mtimer.cancel ();} index++;}}; Mtimer.schedule (Mtimertask, 1000, 1000);

The idea of drawing is probably:

1. The bitmap is obtained from the image resources, and its width and height are attained;

2. Overload the Onmeasure and Onsizechanged functions, set and get the width and height of the control;

3. Use the Porterduffxfermode graphics blending mode to get the desired bitmap;

4. Reload the OnDraw function, and in the function, zoom the bitmap from the previous step to the size of the control to display.


Let's take a look at a few important parts and the rest of the code will be appended.

1. Overloading the Onmeasure function to complete the measurement of the control size

@Overridepublic void onmeasure (int widthmeasurespec, int heightmeasurespec) {int RESULTW = 0;if (Measurespec.getmode ( WIDTHMEASURESPEC) = = measurespec.exactly) {RESULTW = Measurespec.getsize (widthmeasurespec);} else {if ( Measurespec.getmode (widthmeasurespec) = = measurespec.at_most) {RESULTW = Math.min (Bwidth,measurespec.getsize ( Widthmeasurespec));}} int resulth = 0;if (Measurespec.getmode (heightmeasurespec) = = measurespec.exactly) {resulth = Measurespec.getsize ( HEIGHTMEASURESPEC);} else {if (Measurespec.getmode (heightmeasurespec) = = measurespec.at_most) {resulth = Math.min (Bheight, Measurespec.getsize (Heightmeasurespec));}} Setmeasureddimension (RESULTW, resulth);}

If I set the following in the XML file:
<com.example.grownheart.grownheart         android:id= "@+id/grownheart"        android:layout_width= "100DP"        
We set the width and height of the control is the specific value: 100DP, then the Onmeasure function in the measurement of the width of the control Widthmeasurespec/heightmeasurespec GetMode is

measurespec.exactly, the width height of the control is GetSize, which is the 100DP we set.

If we configure the following in XML:

<com.example.grownheart.grownheart         android:id= "@+id/grownheart2"        android:layout_width= "wrap_content "        
Then Widthmeasurespec/heightmeasurespec GetMode is Measurespec.at_most, when the width of the control is the width of the picture resource (or high) and the remaining width (or height) of the parent container is smaller

The one.

2. Get the width and height of the control in the Onsizechanged function

@Overridepublic void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); width = W;heig HT = H;BM = Bitmap.createbitmap (Bwidth, Bheight, Bitmap.Config.ARGB_8888); Mcanvas = new Canvas (BM);

the int w and int h in the parameter are the width and height of the control, respectively.

3. The desired bitmap is obtained through a mix of graphs in the OnDraw.

The border and solid graphs are as follows:


First draw the border graph to bitmap, and then create a new canvas layer to draw a red rectangle on that layer, each time the height of the rectangle is changed. Then set the Piant graphics blending mode, Mpaint.setxfermode (new

Porterduffxfermode (PorterDuff.Mode.DST_IN)), followed by drawing a solid graph into the layer so that overlapping areas can be obtained. The restore is then drawn on the layer. Finally through the Createscaledbitmap will

Bitmap zoom to the control size and display.


Source

public class Grownheart extends View {public Timer mtimer;public timertask mtimertask;public int bwidth;//bitmap width public int bheight;//Bitmap Height public int width;//control width public int height;//control height public Bitmap charm;//resource bitmap public Bitmap charm_on; Resource Bitmap public Bitmap bm;public Canvas mcanvas;public Paint mpaint;public float h;private static int index;public static fi NAL porterduffxfermode modein;public static final Porterduffxfermode modeout;static {modein = new Porterduffxfermode ( PorterDuff.Mode.DST_IN); modeout = new Porterduffxfermode (PorterDuff.Mode.SRC_IN);} Public Grownheart (Context context) {super (context); init ();} Public Grownheart (context context, AttributeSet Attrs) {Super (context, attrs); init ();} public void init () {Mtimer = new Timer (); mtimertask = new TimerTask () {@Overridepublic void run () {postinvalidate (); SYNCHR Onized (This) {if (Index >) {index = 1;mtimer.cancel ();} LOG.I ("Grownheart", "timertask1:index=" + index); index++; LOG.I ("Grownheart", "timertask2:index=" + index);}}};charm = Bitmapfactory.decoderesource (Getresources (), r.drawable.chatroom_charm). Copy (Bitmap.Config.ARGB_8888, true); charm_on = Bitmapfactory.decoderesource (Getresources (), r.drawable.chatroom_charm_on). Copy ( bitmap.config.argb_8888,true); bwidth = Charm_on.getwidth (); bheight = Charm_on.getheight (); H = Bheight/60f;index = 1;mpaint = new Paint (); Mpaint.setantialias (true); Mpaint.setfilterbitmap (false);} public void Starttimer () {mtimer.schedule (mtimertask, 1000, 1000);} @Overridepublic void onmeasure (int widthmeasurespec, int heightmeasurespec) {int RESULTW = 0;if (Measurespec.getmode ( WIDTHMEASURESPEC) = = measurespec.exactly) {RESULTW = Measurespec.getsize (widthmeasurespec);} else {if ( Measurespec.getmode (widthmeasurespec) = = measurespec.at_most) {RESULTW = Math.min (Bwidth,measurespec.getsize ( Widthmeasurespec));}} int resulth = 0;if (Measurespec.getmode (heightmeasurespec) = = measurespec.exactly) {resulth = Measurespec.getsize ( HEIGHTMEASURESPEC);} else {if (Measurespec.getmode (heightmeasureSPEC) = = measurespec.at_most) {resulth = Math.min (Bheight,measurespec.getsize (Heightmeasurespec));}} Setmeasureddimension (RESULTW, resulth);} @Overridepublic void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); width = W;heig HT = H;BM = Bitmap.createbitmap (Bwidth, Bheight, Bitmap.Config.ARGB_8888); Mcanvas = new Canvas (BM); Draw Bitmappublic Bitmap Makebitmap () {//Draw the underlying image first Mcanvas.drawbitmap (charm, 0, 0, mpaint); int i = mcanvas.savelayer (0, 0, b M.getwidth (), Bm.getheight (), Null,canvas.all_save_flag); Mpaint.setcolor (color.red); LOG.I ("Grownheart", "ondraw:index=" + Index) mcanvas.drawrect (new RECTF (0f, (60-index) * H, Bm.getwidth (), Bm.getheight ()), mpaint); Mpaint.setxfermode (Modein); Mcanvas.drawbitmap (charm_on, 0, 0, mpaint); Mpaint.setxfermode (null); Mcanvas.restoretocount (i); return BM;} @Overridepublic void OnDraw (canvas canvas) {Canvas.drawbitmap (Bitmap.createscaledbitmap (Makebitmap (), width, height, true), 0, 0, mpaint);}}

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    android:layout_width=" match_parent "    android:layout_height=" Match_parent "    android:gravity= "center"    tools:context= "com.example.grownheart.MainActivity" >         < Com.example.grownheart.GrownHeart         android:id= "@+id/grownheart"        android:layout_width= "Wrap_content"        android:layout_height= "wrap_content"/>                  </RelativeLayout>

public class Mainactivity extends Activity {@Overrideprotected void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); Grownheart grownheart= (Grownheart) Findviewbyid (R.id.grownheart); Grownheart.starttimer ();}



Android custom Control implementation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.