1. Layout and Java classes for custom control clocks
Attrs.xml under the values file
<?xml version= "1.0" encoding= "Utf-8"?><resources> <declare-styleable name= "Myclock" > <attr name= "CircleColor01" format= "color"/> <attr name= "CircleColor02" format= "color"/> < attr name= "Circlewidth" format= "Dimension"/> </declare-styleable> <declare-styleable name= " Textview "> <attr name=" LineColor "format=" color "></attr> <attr name=" linewidth "format = "Dimension" ></attr> </declare-styleable></resources>
Java
Import Android.content.context;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.paint;import Android.os.handler;import Android.util.attributeset;import Android.view.View;import Java.util.calendar;public class Myclock extends View {private int hour,minute,second; private Boolean running; Private Paint Circlepaint,linepaint,timerpaint,numpaint; Circlepaint---Draw a round brush, linepaint---Draw a tick-mark brush, timerpaint a brush that---a minute, and a number on the clock private int circlecolor01,circlecolor02;// Color private int circlewidth;//clock outer ring width private Handler Handler; Private float density = getresources (). Getdisplaymetrics (). density;//Take phone density public myclock (context context) {Supe R (context); CircleColor01 = 0xffff0000; CircleColor02 = 0xFFFFFFFF; Circlewidth = (int) (4*density); Init (); } public Myclock (Context Context,attributeset attrs) {super (context,attrs); The Attrs.xml defined parameter values are obtained by the corresponding method of Typedarray, and the name+ of the format TypedarrayLine + attribute name TypedArray a = Context.obtainstyledattributes (Attrs, R.styleable.myclock); CircleColor01 = A.getcolor (r.styleable.myclock_circlecolor01,0xffff0000); CircleColor02 = A.getcolor (R.STYLEABLE.MYCLOCK_CIRCLECOLOR02,0XFFFFFFFF); Circlewidth = A.getdimensionpixeloffset (R.styleable.myclock_circlewidth, 4); Init (); A.recycle (); } Private final void init () {hour = 0;minute = 0;second = 0; running = false; Handler = new Handler (); Initialize each brush circlepaint = new paint (); Circlepaint.setantialias (TRUE); Linepaint = new Paint (); Linepaint.setcolor (0xff000000); Linepaint.setantialias (TRUE); Linepaint.setstrokewidth (2.0f * density); Timerpaint = new Paint (); Timerpaint.setcolor (0xff000000); Timerpaint.setantialias (TRUE); Timerpaint.setstrokewidth (3.0f * density); Numpaint = new Paint (); Numpaint.setcolor (0xff000000); Numpaint.setantiAlias (TRUE); Numpaint.settextsize (40); Numpaint.setstrokewidth (3.0f*density); }//Use the Onmeasure method to inquire about the component size protected void onmeasure (int widthmeasurespec,int heightmeasurespec) {int width = meas Urewidth (WIDTHMEASURESPEC); int height = measureheight (heightmeasurespec); int result = Math.min (width,height); Setmeasureddimension (result, result); }//Call this method to get the pattern and size of private int measurewidth (int measurespec) {int result = 0; int specmode = Measurespec.getmode (Measurespec); int specsize = measurespec.getsize (Measurespec); if ((Specmode = = measurespec.exactly) | | (Specmode = = Measurespec.at_most)) {result = Specsize; }else {result = 256; } return result; } private int Measureheight (int measurespec) {int result = 0; int specmode = Measurespec.getmode (Measurespec); int specsize = measurespec.getsize (Measurespec); if ((Specmode = = Measurespec.exacTLY) | | (Specmode = = Measurespec.at_most)) {result = Specsize; }else {result = 256; } return result; }//painting protected void OnDraw (canvas canvas) {super.ondraw (canvas); Circlepaint.setcolor (0XFF0000FF); Canvas.drawcircle (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, circlepaint); Circlepaint.setcolor (CIRCLECOLOR02); Canvas.drawcircle (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2-circlewidth, circlepaint); for (int i = 1;i<=12;i++) {canvas.save (); Canvas.rotate (30*i,this.getwidth ()/2, This.getheight ()/2); Canvas.drawline (This.getwidth ()/2,25*density,this.getwidth ()/2,circlewidth + 1*density, linePaint); Canvas.drawtext ("" +i,this.getwidth ()/2,20*density+65,numpaint); Canvas.restore (); } for (int i = 1;i<=60; i++) {canvas.save (); Canvas.rotate (6*i, This.getwidth ()/2, This.getheight ()/2); Canvas.drawline (This.getwidth ()/2,15*density,this.getwidth ()/2,circlewidth + 1*density, linePaint); Canvas.drawtext ("" +i,this.getwidth ()/2,20*density+60,numpaint); Canvas.restore (); } canvas.save (); Canvas.rotate (Hour * + MINUTE/2, this.getwidth ()/2, This.getheight ()/2); Timerpaint.setstrokewidth (5.0f * density); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, Circlewidth + (This.getheight ()/4) * den sity, Timerpaint); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, This.getheight ()/2-(THIS.GETW Idth ()/10-circlewidth) *density, timerpaint); Canvas.restore (); Canvas.save (); Canvas.rotate (minute * 6, This.getwidth ()/2, This.getheight ()/2); Timerpaint.setstrokewidth (4.0f * density); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, CIRCLEwidth + (This.getheight ()/12) * density, timerpaint); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, This.getheight ()/2-(THIS.GETW Idth ()/8-circlewidth) *density, timerpaint); Canvas.restore (); Canvas.save (); Canvas.rotate (Second*6, This.getwidth ()/2, This.getheight ()/2); Timerpaint.setstrokewidth (3.0f*density); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, Circlewidth + (This.getheight ()/18) * density, timerpaint); Canvas.drawline (This.getwidth ()/2, This.getheight ()/2, This.getwidth ()/2, This.getheight ()/2-(this.getwidth ()/7-circlewidth) *density, timerpaint); Canvas.restore (); } Private class TimerTask implements runnable{public void run () {while (running) {try {thread.sleep (1000); }catch (Interruptedexception e) {return; } Calendar C = calendar.getinstance (); hour = C.get (Calendar.hour); minute = C.get (Calendar.minute); Second = C.get (Calendar.second); Handler.post (New Runnable () {public void run () {MyClock.this.invalidate (); } }); }}} protected void Onattachedtowindow () {Super.onattachedtowindow (); Start (); } public void Ondetachedfromwindow () {Super.ondetachedfromwindow (); Stop (); public void Start () {if (running = = False) {running = true; Thread t = new Thread (new TimerTask ()); T.start (); }} public void Stop () {running = false; }}
2. Add a custom on an existing component
Import Android.content.context;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.paint;import Android.util.attributeset;import Android.widget.textview;public class TextView Extends TextView {private int linecolor; private int linewidth; Private Paint Linepaint; Public Textview (Context context) {super (context); linecolor=0xff000000; linewidth=2; Init (); } public Textview (Context Context,attributeset attrs) {super (context,attrs); TypedArray a=context.obtainstyledattributes (Attrs,r.styleable.textview); Linecolor=a.getcolor (r.styleable.textview_linecolor,0xff000000); Linewidth=a.getdimensionpixeloffset (r.styleable.textview_linewidth,2); Init (); A.recycle (); } Private final void init () {linepaint=new Paint (); Linepaint.setcolor (LineColor); Linepaint.setantialias (TRUE); Linepaint.setstrokewidth (linewidth); } protected void OnDraw (canvas canvas) {super.ondraw (canvas); Canvas.drawline (0,this.getheight (), This.getwidth (), This.getheight (), linepaint); }}
3. Layout
<?xml version= "1.0" encoding= "Utf-8"? ><linearlayout xmlns:android= "http://schemas.android.com/apk/res/ Android "xmlns:tools=" Http://schemas.android.com/tools "xmlns:app=" Http://schemas.android.com/apk/res-auto "Andro Id:layout_width= "Match_parent" android:layout_height= "match_parent" android:paddingbottom= "@dimen/activity_ Vertical_margin "android:paddingleft=" @dimen/activity_horizontal_margin "android:paddingright=" @dimen/activity_ Horizontal_margin "android:paddingtop=" @dimen/activity_vertical_margin "tools:context=" Com.rj141.sb.myclockview.MainActivity "android:orientation=" vertical "> <com.rj141.sb.myclockview.textview Android:layout_width= "Wrap_content" android:layout_height= "wrap_content" android:layout_gravity= "center" App:linecolor= "#FFFF0000" android:textsize= "24DP" app:linewidth= "3DP" android:text= "@string/cl Ock "/> <com.rj141.sb.myclockview.myclock android:layout_margintop= "10DP" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:i D= "@+id/id_clock" App:circlecolor01 = "#FF0000FF" App:circlecolor02 = "#ffffff" app:circlewidth = "4d P "/> <linearlayout android:layout_width=" match_parent "android:layout_height=" Wrap_content " android:orientation= "Horizontal" > <button android:id= "@+id/start" android:layout_width= "Match_parent" android:layout_height= "Wrap_content" android:layout_weight= "1" Android:tex t= "@string/start"/> <button android:id= "@+id/stop" android:layout_width= "Match_parent" android:layout_height= "Wrap_content" android:layout_weight= "1" android:text= "@string/stop "/> </LinearLayout></LinearLayout>
4. Display
Import Android.support.v7.app.appcompatactivity;import Android.os.bundle;import Android.view.view;import Android.widget.button;public class Mainactivity extends appcompatactivity implements view.onclicklistener{private but ton start,stop; Private Myclock Myclock; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.activity_main); myclock= (Myclock) This.findviewbyid (R.id.id_clock); Start= (Button) This.findviewbyid (R.id.start); Start.setonclicklistener (this); stop= (Button) This.findviewbyid (r.id.stop); Stop.setonclicklistener (this); } @Override public void OnClick (View v) {switch (V.getid ()) {R.ID.START:MYCL Ock.start (); Break Case R.id.stop:myclock.stop (); Break Default:break; } }}
Custom Clock controls