1. Steps to customize the view:
a.在values/attrs.xml文件中创建自定义的属性;b.自定义view,在view的构造方法中获取到自定义的属性;c.重写onDraw()方法;d.重写onMeasure()方法。
To create a custom property in a Values/attrs.xml file
<?xml version= "1.0" encoding= "Utf-8"?><resources> <attr name="Texttitle" format="string"/> <attr name="TextColor" format="Color"/> <attr name="textsize" format="Dimension"/> <declare-styleable name="Mytextview"> <attr name="Textsize"/> <attr name="Texttitle"/> <attr name="TextColor"/> </declare-styleable></Resources>
Set a custom TextView, set the font, color and size of the properties.
<?xml version= "1.0" encoding= "Utf-8"?><relativelayout xmlns: Android = "http://schemas.android.com/apk/res/android" xmlns:tools =" Http://schemas.android.com/tools " xmlns:keke = "Http://schemas.android.com/apk/res-auto" android:layout_width = "match_parent" android:layout_height = "match_parent" > <com.best.keke.mycustondemo.MyCustomViewandroid:layout_width="Match_parent" android:layout_height="Match_parent"android:text="Hello world!" Keke:textcolor="#78101ff1"keke:textsize= "30sp" android:layout_ Centerinparent="true"keke:texttitle="Hello ah ah"/> </relativelayout>
Note: Be sure to declare your own namespace here.
xmlns:keke="http://schemas.android.com/apk/res-auto"
Custom view, getting custom properties in the view's construction method
Public class mycustomview extends TextView { PrivateString Texttitle;Private intTextColor;Private intTextSize;PrivatePaint paint;PrivateRect rect; Public Mycustomview(Context context) { This(Context,NULL); } Public Mycustomview(context context, AttributeSet attrs) { This(Context, Attrs,0); } Public Mycustomview(context context, AttributeSet attrs,intDEFSTYLEATTR) {Super(Context, attrs, defstyleattr);//Gets the properties of the custom styleTypedArray array = context.obtainstyledattributes (Attrs, R.styleable.mytextview, Defstyleattr,0);intCount = Array.getindexcount (); for(inti =0; I < count; i++) {intattr = Array.getindex (i);Switch(attr) { CaseR.styleable.mytextview_textcolor://Set the default color to blueTextColor = Array.getcolor (Attr,color.blue); Break; CaseR.styleable.mytextview_textsize://Set the size of the font, the default is 16SPTextSize = Array.getdimensionpixelsize (attr, (int) Typedvalue.applydimension (Typedvalue.complex_unit_dip, -, Getresources (). Getdisplaymetrics ()); Break; CaseR.styleable.mytextview_texttitle://Set the title of the fontTexttitle = array.getstring (attr); Break; } }//Call this method to make it easy to reuse the properties in the view. Recycles the TypedArray, to being re-used by a later caller. After calling this function you must not ever touch the typed array again.Array.recycle ();//Gets the width height of the drawing textPaint =NewPaint (); Paint.settextsize (textSize); Paint.setcolor (TextColor);//Create a rectangleRect =NewRect ();/** * @param text String to measure and return the word it bounds to measure * @param start Ind Ex of the first char in the string to measure the starting position of the measurement * @param End 1 past the last char in the Strin G measure the position of the last string measured * @param bounds Returns The unioned bounds of all the text. Must be Rect object * allocated by the caller. */Paint.gettextbounds (Texttitle,0, Texttitle.length (), rect); }
Override OnDraw (), Onmeasure () method
@Override protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas); Paint.setcolor (Color.green);//Set the length and width height of the rectangleCanvas.drawrect (0,0, Getmeasuredwidth (), Getmeasuredheight (), paint); Paint.setcolor (TextColor);//drawrect (float left, float top, float right, float bottom,paint Paint)Canvas.drawtext (Texttitle, getwidth ()/2-Rect.width ()/2, GetHeight ()/2+ rect.height ()/2, paint); }@Override protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {Super. Onmeasure (Widthmeasurespec, Heightmeasurespec); }
public void DrawRect (float-left, float-top, float right, float bottom,paint Paint)
Description: Draw a moment shape. Note that the parameters to draw the rectangle are different from the methods in Java.
The parameters of the DrawRect () method are illustrated below:
When we changed the layout of the android:layout_width= "100DP", android:layout_height= "100DP" to wrap_cotent, we found that it looked like this:
When you change to a match_parent, it's like this:
As you can see, for a custom view to support the Wrap_content attribute, you must override the Onmeasure () method to make the wrap_content size.
This is because the default Onmeasure () method in the view class supports only exactly mode, so if the control does not override the Onmeasure () method when it is customized, the control can only respond to the specific width and height values you have set or match _parent property, if you want to support wrap_contaent Zodiac, you must override the Onmeasure () method for a long time.
Android gives us a Measurespec class to help us measure view,measurespec is a 32-bit int value, where the high two bits are the measured pattern, and the low 30 bits make us measure the size:
3 modes in the measurement:
exactly: In precise mode, when the Layout_width or Layout_height property of our control is the specific attribute value, such as LAYOUT_WIDTH=100DP, the system uses exactly mode.
at_most: Maximum mode, when the Layout_width or Layout_height property of our control is wrap_content, the size of the control at this time does not exceed the maximum size allowed by the parent control.
UNSPECIFIED: Non-precise mode, does not specify its size measurement mode, how big the view is, usually when the custom view is drawn to use.
Overriding the Onmeasure () method
@Override protected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {//super.onmeasure (Widthmeasurespec, heightmeasurespec); //Get to wide-height measurement mode and measured values intWidthmode = Measurespec.getmode (Widthmeasurespec);intWidthsize = Measurespec.getsize (Widthmeasurespec); LOG.E ("Tag",""+ Widthmode + widthsize);intHeightmtode = Measurespec.getmode (Heightmeasurespec);intHeightsize = Measurespec.getsize (Heightmeasurespec); LOG.E ("Tag",""+ Heightmtode + heightsize);intWidthintHeight//Wide If the measurement is accurate if(Widthmode = = measurespec.exactly) {width = widthsize; }Else{paint.settextsize (textSize); Paint.gettextbounds (Texttitle,0, Texttitle.length (), rect);intTextWidth = Rect.width ();intMeasurewidth = Getpaddingleft () + TextWidth + getpaddingright (); width = measurewidth; }if(Heightmtode = = measurespec.exactly) {height = heightsize; }Else{paint.settextsize (textSize); Paint.gettextbounds (Texttitle,0, Texttitle.length (), rect);floatTextHeight = Rect.height ();intMeasureheight = (int) (Getpaddingtop () + TextHeight + getpaddingbottom ()); Height = measureheight; }//Reset the space's width and heightSetmeasureddimension (Width,height); }
Effect after overriding the Onmeasure () method:
Add noise and horizontal lines to your custom TextView to emulate the style of the CAPTCHA
The method of writing an underscore and drawing a dot in the OnDraw () method.
//Get to Custom view width height Final intHeight = getheight ();Final intwidth = getwidth ();//Draw small dots int[] point; for(inti =0; I < -; i++) {point = GetPoint (height, width);/** * drawcircle (float cx, float CY, float radius, paint paint) * Float CX: x coordinate of the center of the circle. * Float CY: The y-coordinate of the center point. * Float radius: radius of the circle. * Paint Paint: The brush used when drawing. */Canvas.drawcircle (point[0], point[1],1, paint); }int[] line; for(inti =0; I < -; i + +) {line = GetLine (height, width);/** * StartX: The x-coordinate of the starting endpoint. *starty: The y-coordinate of the starting endpoint. *STOPX: Terminates the x-coordinate of the endpoint. *stopy: Terminates the y-coordinate of the endpoint. *paint: The brush used to draw the line. */Canvas.drawline (line[0], line[1], line[2], line[3], paint); }
Public int[]GetLine(intHeightintwidth) {int[] Tempchecknum = {0,0,0,0}; for(inti =0; I <4; i+=2) {Tempchecknum[i] = (int) (Math.random () * width); Tempchecknum[i +1] = (int) (Math.random () * height); }returnTempchecknum; }Private int[]GetPoint(intHeightintwidth) {int[] Tempchecknum = {0,0,0,0}; tempchecknum[0] = (int) (Math.random () * width); tempchecknum[1] = (int) (Math.random () * height);returnTempchecknum; }
The styles are as follows:
Verification code with noise and horizontal lines custom view