Recently due to project needs, need to self-control a watch view, and add some business logic, so according to customize a view of the steps, made a clock, see:
Here is my custom view code, referring to the online god code, I did some of the business logic of the project, optimized the whole view.
Package Com.hp.clock;import Android.content.broadcastreceiver;import Android.content.context;import Android.content.intent;import Android.content.intentfilter;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.paint;import Android.graphics.paintflagsdrawfilter;import Android.graphics.drawable.drawable;import Android.os.handler;import Android.text.format.dateutils;import Android.text.format.time;import android.util.attributeset;import android.view.view;/** * Clock control * */public class Clockview extends View {private time mcalendar;private final drawable mhourhand;//clock hour picture private final drawable Mminuteha nd Clock minute hand picture private final drawable Msecondhand; Clock seconds hand Picture private final drawable mdial; When the clock disk picture private final int mdialwidth; Component width private final int mdialheight; Component Height Private Boolean mattached;private final Handler mhandler = new Handler ();p rivate float mseconds; Number of seconds, e.g. 23sprivate float mminutes; Number of minutes, e.g. 12mprivate float mhour; Number of hours, e.g. 5hprivAte boolean mchanged;private final Context mcontext;//private String mtimezoneid;private int mtimezoneoffset = 0; Time difference, unit is the hour private Boolean mnoseconds = false; Used to determine if it is necessary to display the second hand public clockview (context context) {This (context, null);} Public Clockview (context context, AttributeSet Attrs) {This (context, attrs, 0);} Public Clockview (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, defstyle); mcontext = Context;m Calendar = new Time ();//Here Gets the custom component properties, defined in Attr.xml, as described in activity_main.xml layout file Typedarray a = Context.obtainstyledattributes (attrs,r.styleable.clockview); mdial = A.getdrawable (R.styleable.ClockView_ dialogdrawable); Mhourhand = A.getdrawable (r.styleable.clockview_hourhanddrawable); Mminutehand = A.getDrawable ( r.styleable.clockview_minutehanddrawable); Msecondhand = A.getdrawable (r.styleable.clockview_secondhanddrawable); Mdialwidth = Mdial.getintrinsicwidth (); mdialheight = Mdial.getintrinsicheight (); A.recycle ();} /* * Component Attach to the callback on the window * * @see ANDROID.VIEW.VIEW#ONATTACHedtowindow () */@Overrideprotected void Onattachedtowindow () {Super.onattachedtowindow ();//Prevent duplicate registration of the listener if (!mattached) { mattached = true;intentfilter Filter = new Intentfilter (); filter.addaction (Intent.action_time_tick); filter.addAction (intent.action_time_changed); filter.addaction (intent.action_timezone_changed);//register monitoring, monitor time Change Event GetContext (). Registerreceiver (Mintentreceiver, filter, Null,mhandler);} Mcalendar = new Time ();//Get Latest ontimechanged ();//clock changes 1 times per second (Mclocktick);} /* * Component callback from component Detach * @see Android.view.view#ondetachedfromwindow () */@Overrideprotected void Ondetachedfromwindow () { Super.ondetachedfromwindow ();//unregister the listener and make the loop stop if (mattached) {getcontext (). Unregisterreceiver (Mintentreceiver); Removecallbacks (mclocktick); mattached = false;}} /* is called before drawing the clock component (OnDraw) to determine the size of the clock component * @see android.view.view#onmeasure (int, int) */@Overrideprotected void onmeasure (i NT Widthmeasurespec, int heightmeasurespec) {int widthmode = Measurespec.getmode (widthmeasurespec); int widthSize = Measurespec.geTsize (widthmeasurespec); int heightmode = Measurespec.getmode (heightmeasurespec); int heightsize = MeasureSpec.getSize (heightmeasurespec); float Hscale = 1.0f;float Vscale = 1.0f;//Sets the width of the component if it is less than the size of the clock wheel picture, then calculates the magnification if (widthmode! = Measurespec.unspecified && Widthsize < mdialwidth) {Hscale = (float) widthsize/(float) mdialwidth;} Ditto, here is the height if (heightmode! = measurespec.unspecified && heightsize < mdialheight) {Vscale = (float) heightsize /(float) mdialheight;} Ensure that the width of the component is consistent with the float scale = Math.min (Hscale, Vscale); Setmeasureddimension (Resolvesize ((int) (Mdialwidth * scale), WIDTHMEASURESPEC), resolvesize ((int) (Mdialheight * scale), heightmeasurespec)); /* Callback when the component size changes, such as the wide height of the component in the external setting * * @see android.view.view#onsizechanged (int, int, int, int) */@Overrideprotected void on SizeChanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); mchanged = true;} /* Component Draw Callback * @see Android.view.view#ondraw (android.graphics.Canvas) */@Overrideprotected void OnDraw (Canvas canvas) {super.ondraw (canvas); Canvas.setdrawfilter (new Paintflagsdrawfilter (0, Paint.anti_alias_flag| Paint.filter_bitmap_flag)); Anti-aliasing Boolean changed = Mchanged;if (changed) {mchanged = false;} Final drawable dial = Mdial;int w = dial.getintrinsicwidth (); int h = dial.getintrinsicheight (); int availablewidth = GetWid th (); int availableheight = H;int x = availablewidth/2;int y = Availableheight/2;boolean scaled = false;//if necessary, proportional scaling, Uniform if (Availablewidth < W | | Availableheight < h) {scaled = True;float scale = Math.min ((float) availablewidth/( float) W, (float) availableheight/(float) h); Canvas.save (); Canvas.scale (scale, scale, x, y);} if (changed) {dial.setbounds (X-(W/2), Y-(H/2), X + (W/2), Y + (H/2));} Dial.draw (canvas); Draw the dial if (!mnoseconds) {Drawhand (canvas, Msecondhand, x, y, mseconds/60.0f * 360.0f,changed);//Draw the second hand}drawhand (canvas, Mminutehand, x, y, mminutes/60.0f * 360.0f, changed); Draw the minute hand drawhand (canvas, Mhourhand, x, y, mhour/12.0f * 36)0.0f, changed); Draw the hour hand if (scaled) {Canvas.restore ();}} /** * seconds to draw * * @param canvas * @param hand * @param x * @param y * @param angle * @param changed */private void Drawhan D (Canvas canvas, drawable hand, int x, int y,float angle, Boolean changed) {Canvas.save (); canvas.rotate (angle, x, y); if (c hanged) {Final int w = hand.getintrinsicwidth (); final int h = hand.getintrinsicheight (); Hand.setbounds (X-(W/2), Y-(H /2), X + (W/2), Y + (H/2));} Hand.draw (canvas); Canvas.restore ();} /** * Time Change callback, calculates the current cent */private void Ontimechanged () {mcalendar.settonow (); if (Mtimezoneoffset! = 0) {Long offset =-MCal Endar.gmtoff * + (Mtimezoneoffset * 3600000), if (offset! = 0) {Mcalendar.set (Mcalendar.tomillis (false) + offset);}} if (Mtimezoneid! = null) {//mcalendar.switchtimezone (Mtimezoneid);//}int hour = mcalendar.hour;int minute = Mcalendar.minute;int second = mcalendar.second;//long Millis = System.currenttimemillis ()% 1000;mseconds = second;//(fl Oat) ((second * + Millis)/166.666); mminutes = minute + Second/60.0f;mhour = hour + mminutes/60.0f;mchanged = true;updatecontentdescription (MCalenda R);} /** * Time Change receiver, callback does not do logical processing, because Mclocktick loop is used */private final broadcastreceiver mintentreceiver = new Broadcastreceiver () {@Overridepublic void OnReceive (context context, Intent Intent) {//if (Intent.getaction (). Equals ( intent.action_timezone_changed)) {//String TZ = Intent.getstringextra ("Time-zone");//Mcalendar = new Time ( Timezone.gettimezone (TZ). GetID ());//}//ontimechanged ();//invalidate ();}};/ * * time interval 1s loop 1 times */private final Runnable Mclocktick = new Runnable () {@Overridepublic void run () {ontimechanged (); Invalida Te (); ClockView.this.postDelayed (Mclocktick, 1000);}; private void Updatecontentdescription (Time time) {Final int flags = Dateutils.format_show_time | Dateutils.format_24hour; String contentdescription = Dateutils.formatdatetime (Mcontext,time.tomillis (FALSE), flags); Setcontentdescription ( contentdescription);} public void Settimezone (String id) {Mtimezoneid = id;//ontimechanged ();//}/** * Time difference, hours * * @param timezoneoffset */public void Settimezoneoffset (int tim Ezoneoffset) {this.mtimezoneoffset = Timezoneoffset;} /** * Set Whether the second hand is required * * @param enable */public void Enableseconds (Boolean enable) {mnoseconds =!enable;}}
Android Custom Clockview