Objective
Lately I've been on the custom view bar, and I'm even addicted to the obsession. As a rookie I naturally have to look up a lot of information, learning the code of the Great God, this is not, the first two days in Guo Shen in the micro-letter public number pushed a custom control article-step by step to achieve exquisite clock interface. is suitable for me this kind of rookie to study, the idle is all right, I am almost according to Gourd to draw the scoop also to write a custom dial view, now the pure most notes record. First show the effect of the picture:
Let's get down to business.
Custom Dial Properties
First, add the dial in the Attrs file. Custom properties
<declare-styleable name= "Watchview" > <attr name= "Watchradius" format= "Dimension"/>//Dial radius <attr name= " Watchpadding "format=" Dimension "/>/dial relative to control border distance <attr name=" watchscalepadding "format=" Dimension "/>// Scale relative to dial distance <attr name= "Watchscalecolor" format= "color|reference"/>//Regular tick color <attr name= "Watchscalelength" format= "dimension|reference"/>//Regular tick length <attr name= "Watchhourscalecolor" format= "dimension|reference"/>// The whole point tick color <attr name= "watchhourscalelength" format= "dimension|reference"/>//hour scale length <attr name= "HourPointColor" "format=" color|reference "/>//Clockwise color <attr name=" hourpointlength "format=" dimension|reference "/>//hour length < attr name= "Minutepointcolor" format= "color|reference"/>/the minute hand color <attr name= "Minutepointlength" Dimension|reference "/>//minute hand length <attr name=" Secondpointcolor "format=" color|reference "/>//Seconds color <attr name= "Secondpointlength" format= "dimension|reference"/>//hand seconds length <attr naMe= "Timetextsize" format= "dimension|reference"/>/dial Font size <attr name= "Timetextcolor" format= "Color|reference" />/Dial Font color </declare-styleable>
To get a custom property in the custom view's constructed method species
First, declare the property variable as follows:
<span style= "FONT-SIZE:14PX;" >/** Dial Margin * *
private float mwatchpadding = 5;
/** dial and tick margin * *
private float mwatchscalepadding = 5;
/** Dial RADIUS * *
private float Mwatchradius =;
/** Dial Scale length * *
private float mwatchscalelength;
/** Dial Scale color *
/private int mwatchscalecolor = Color.Black;
/** table Consolidation Point Scale length * *
private float mhourscalelength = 8;
/** table Consolidation Point scale color *
/private int mhourscalecolor = Color.Blue;
/** dial Hand color
/private int mhourpointcolor = Color.Black;
/** Dial Clock length
/private float mhourpointlength =;
/** dial minute hand color
/private int mminutepointcolor = Color.Black;
/** dial minute hand length * *
private float mminutepointlength = 130;
/** dial seconds color
/private int msecondpointcolor = color.red;
/** Dial seconds Length * *
private float msecondpointlength = 160;
/** dial Tail pointer length * *
private float mendpointlength;
/** Dial Digital color *
/private int mtimetextcolor = Color.Black;
/** Dial Digital Size * *
private int mtimetextsize = 15;</span>
To get a custom attribute in a constructed method type
<span style= "FONT-SIZE:14PX;"
> Public Watchview (Context, AttributeSet attrs) {Super (context, attrs);
TypedArray array = context.obtainstyledattributes (Attrs,r.styleable.watchview);
int n = array.getindexcount ();
for (int i = 0;i<n;i++) {int attr = Array.getindex (i); Switch (attr) {Case R.styleable.watchview_watchradius:mwatchradius = array.getdimensionpixelsize (attr,myutil.dip2px
(context,60));
Break Case r.styleable.watchview_watchpadding:mwatchpadding = array.getdimensionpixelsize (attr,MyUtil.dip2px (context,5)
);
Break Case r.styleable.watchview_watchscalepadding:mwatchscalepadding = array.getdimensionpixelsize (attr,MyUtil.dip2px (
context,3));
Break Case r.styleable.watchview_watchscalelength:mwatchscalelength = array.getdimensionpixelsize (attr,MyUtil.dip2px (
context,5));
Break
Case R.styleable.watchview_watchscalecolor:mwatchscalecolor = Array.getcolor (attr, Color.parsecolor ("#50000000"));
Break Case R.styleable.watchview_watchhourscaleLength:mhourscalelength = Array.getdimensionpixelsize (attr,myutil.dip2px (context,10));
Break
Case R.styleable.watchview_watchhourscalecolor:mhourscalecolor = Array.getcolor (Attr,color.black);
Break Case r.styleable.watchview_hourpointlength:mhourpointlength = array.getdimensionpixelsize (attr,MyUtil.dip2px (
context,35));
Break
Case R.styleable.watchview_hourpointcolor:mhourpointcolor = Array.getcolor (Attr,color.black);
Break Case r.styleable.watchview_minutepointlength:mminutepointlength = array.getdimensionpixelsize (attr,MyUtil.dip2px (
context,40));
Break
Case R.styleable.watchview_minutepointcolor:mminutepointcolor = Array.getcolor (Attr,color.black);
Break Case r.styleable.watchview_secondpointlength:msecondpointlength = array.getdimensionpixelsize (attr,MyUtil.dip2px (
context,50));
Break
Case R.styleable.watchview_secondpointcolor:msecondpointcolor = Array.getcolor (Attr,color.blue);
Break Case r.styleable.watchview_timetextsize:mtimetextsize = ARRay.getdimensionpixelsize (attr,myutil.dip2px (context,15));
Break
Case R.styleable.watchview_timetextcolor:mtimetextcolor = Array.getcolor (Attr,color.black);
Break
} array.recycle (); }</span>
To set the size of a control
This is certainly rewriting the Onmeasure method, where we deal with the simple point, as shown in the following code, when we set the width of the control to WRAP_ Content (that is, measurespec.unspecifed), we set the width to the default value (wrapcontentsize) and the disk radius + disk margin (mwatchradius+mwatchpadding) between the maximum value, In other cases, take the system to get the value. Of course, as a strict control, it is certainly not possible to deal with this simply. In the project, we need to modify the code in accordance with our requirements to fit.
<span style= "FONT-SIZE:14PX;" > @Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
int wrapcontentsize = 1000;
int widthsize = measurespec.getsize (widthmeasurespec);
int widthmode = Measurespec.getmode (widthmeasurespec);
int heightsize = measurespec.getsize (heightmeasurespec);
int heightmode = Measurespec.getmode (heightmeasurespec);
if (Widthmode = = Measurespec.unspecified && Heightmode = = measurespec.unspecified) {
wrapcontentsize = (int) Math.max (wrapcontentsize,mwatchradius+mwatchpadding);
Setmeasureddimension (wrapcontentsize,wrapcontentsize);
} else {
setmeasureddimension (widthsize,heightsize);
}
} </span>
Overriding the OnDraw method
Come to the most crucial real draw dial moment. First, step by step, initialize our brushes (my habit, write a initpaint method)
<span style= "FONT-SIZE:14PX;" > private void Initpaint () {
mpaint = new Paint ();
Mpaint.setantialias (true);
Mpaint.setcolor (color.white);
Mpaint.setstyle (Paint.Style.FILL);
} </span>
In order not to repeat, easy to understand, I directly show the code in the code to explain
Before we start painting, we move the brush to the center point of the control, as follows:
<span style= "FONT-SIZE:14PX;" > @Override
protected void OnDraw (Canvas Canvas) {
canvas.translate (getwidth ()/2,getheight ()/2);
} </span>
The first step, draw the dial
<span style= "FONT-SIZE:14PX;" >/**
* Draw Dial
* @param canvas
/
private void Paintwatchboard (canvas canvas) {
initpaint (); C16/>canvas.save ();
Canvas.drawcircle (0,0,mwatchradius,mpaint); Draw a disc
canvas.restore ();
} </span>
Note: Call the Canvas.save () method before each drawing, save the brush properties, call the Canvas.restore () method after the drawing is finished, and reset the brush properties
Here is not to show each of the finished painting after the effect of the picture.
Second step, draw a scale + the whole point time number (the scale starts at 12)
<span style= "FONT-SIZE:14PX;" >/** * Drawing scale and the whole point number * @param canvas * * private void Paintscale (canvas canvas) {int linelength;//tick mark length Canvas.save ()
;
for (int i = 0;i<60;i++) {if (i%5 = 0) {//The whole point tick brush-related properties Mpaint.setstrokewidth (myutil.dip2px (GetContext (), 1.5f));
Mpaint.setcolor (Mhourscalecolor);
LineLength = myutil.dip2px (GetContext (), 8);
Canvas.drawline (0,-mwatchradius+mwatchscalepadding,0,-mwatchradius+mwatchscalepadding+linelength,mpaint);
Mpaint.setcolor (Mtimetextcolor);
Mpaint.settextsize (mtimetextsize); Canvas.drawtext (mtimes[i/5],-mtimetextsize/2,-mwatchradius+mwatchscalepadding + lineLength+mTimeTextSize,mPaint)
//The position of the whole point marks the whole hour number}else {///not on the hour scale brush-related properties Mpaint.setstrokewidth (myutil.dip2px (GetContext (), 0.8f));
Mpaint.setcolor (Mwatchscalecolor);
LineLength = myutil.dip2px (GetContext (), 5);
Canvas.drawline (0,-mwatchradius+mwatchscalepadding,0,-mwatchradius+mwatchscalepadding+linelength,mpaint);
Canvas.rotate (6);//each time you finish drawing a tick mark, the brush rotates 6 degrees clockwise (360/60, the angle difference between the two adjacent scales is 6 degrees)}Canvas.restore (); }</span>
Where the whole point number I used to represent the Roman numerals
<span style= "FONT-SIZE:14PX;" >private string[] Mtimes = {"XII", "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ", "Ⅵ", "Ⅶ", "Ⅷ", "Ⅸ", "Ⅹ", "XI"};</span>
Step three, draw the hour hand, the minute hand, the second hand, and other decorations
Considering the length of the hand, minute and second hand, I have deliberately defined three brushes to draw the hour hand, the minute hand and the second hand.
Similarly, the pointer brush is initialized first:
<span style= "FONT-SIZE:14PX;" >/**
* Initialization pointer/
private void Initpointpaint () {
mhourpaint = new Paint ();
Mhourpaint.setantialias (true);
Mhourpaint.setstyle (Paint.Style.FILL);
Mhourpaint.setstrokewidth ();
Mhourpaint.setcolor (Mhourpointcolor);
Mminutepaint = new Paint ();
Mminutepaint.set (mhourpaint);
Mminutepaint.setstrokewidth (a);
Mminutepaint.setcolor (Mminutepointcolor);
Msecondpaint = new Paint ();
Msecondpaint.set (mhourpaint);
Msecondpaint.setstrokewidth (7);
Msecondpaint.setcolor (Msecondpointcolor);
Mendpointlength = MWATCHRADIUS/6; (cosmetic part) The length of the pointer's tail, defined as one-sixth of the dial radius
Draw a pointer
<span style= "FONT-SIZE:14PX;" >/**
* Draw pointer
* @param canvas
/
private void Paintpoint (canvas canvas) {
initpointpaint ();
Calendar C = calendar.getinstance (); Take the current time
int hour = C.get (calendar.hour_of_day);
int minute = C.get (Calendar.minute);
int second = C.get (Calendar.second);
Draw the hour
canvas.save ();
Canvas.rotate (hour*30);
Canvas.drawline (0,0,0,-mhourpointlength,mhourpaint);
Canvas.drawline (0,0,0,mendpointlength,mhourpaint);
Canvas.restore ();
Draw the minute hand
Canvas.save ();
Canvas.rotate (minute*6);
Canvas.drawline (0,0,0,-mminutepointlength,mminutepaint);
Canvas.drawline (0,0,0,mendpointlength,mminutepaint);
Canvas.restore ();
Draw the second hand
Canvas.save ();
Canvas.rotate (second*6);
Canvas.drawline (0,0,0,-msecondpointlength,msecondpaint);
Canvas.drawline (0,0,0,mendpointlength,msecondpaint);
Canvas.restore ();
} </span>
OK, it's almost all there, just call it in the OnDraw.
<span style= "FONT-SIZE:14PX;" > @Override
protected void OnDraw (Canvas Canvas) {
canvas.translate (getwidth ()/2,getheight ()/2);
Paintwatchboard (canvas); Draw Dial
Paintscale (canvas),//Draw scale
paintpoint (canvas),//Draw pointer
canvas.drawcircle (0,0,15,msecondpaint); For the sake of beauty, it also makes the dial closer to what we look like in life, and I draw a red dot in the center of the disk to decorate the
second hand postinvalidatedelayed (1000);//Draw}</span> every other minute
(⊙v⊙) Well, custom view is done, and we'll call it in the layout file. Look at the effect.
<span style= "FONT-SIZE:14PX;" ><?xml version= "1.0" encoding= "Utf-8"?> <relativelayout xmlns:android=
"http://schemas.android.com" /apk/res/android "
xmlns:zhusp=" Http://schemas.android.com/apk/res-auto "
android:layout_width=" Match_ Parent "
android:layout_height=" match_parent "
android:background=" @color/coloraccent >
< Com.wondertek.propertyanimatordemo.WatchView
android:layout_width= "wrap_content"
android:layout_height = "Wrap_content"
zhusp:timetextsize= "20DP"
zhusp:watchradius= "150DP"
zhusp:hourpointlength= "80DP"
zhusp:minutepointlength= "100DP"
zhusp:secondpointlength= "115DP"/>
</RelativeLayout> </span>
Finally, my static effect here is this: