Original address: Http://android.xsoftlab.net/training/custom-views/custom-drawing.html#draw
The most important part of customizing view is what it looks like. Custom View drawing is based on the needs of the application or is simple or complex. This lesson covers most of the common knowledge points.
Overriding the OnDraw () method
One of the important steps in drawing a custom view is to rewrite its OnDraw () method. The method contains a canvas object as a parameter that enables the view to draw its own contents. The canvas class defines methods for drawing text, lines, bitmaps, and many other underlying physical shapes. You can use these methods in the OnDraw () method to create your own UI effects.
Before you begin any drawing, you must first create a paint object. The following sections discuss the knowledge of paint.
Creating a drawing Object
The Android.graphics framework divides the plot into two areas:
- What to draw, controlled by canvas
- How to draw, controlled by paint
For example, Canvas provides a way to draw lines, while paint defines the color of the lines. Canvas has a way to draw a rectangle, and paint defines whether you want the color to fill the rectangle. In short, canvas defines the shapes you draw on the screen, and paint defines the colors, styles, fonts, and so on for those shapes.
So before you start drawing anything, you need to create one or more paint objects first. Example Piechart puts the work in a method named Init, which is called by the constructor method:
private void init () {mtextpaint = new Paint (paint.anti _alias_flag); Mtextpaint.setcolor (Mtextcolor); if (Mtextheight = = 0 ) {mtextheight = Mtextpaint.gettextsize (); } else {mtextpaint.settextsize (mtextheight); } mpiepaint = new Paint (Paint.anti_alias_flag); Mpiepaint.setstyle (Paint.Style.FILL); Mpiepaint.settextsize (Mtextheight); Mshadowpaint = new Paint (0 ); Mshadowpaint.setcolor (0xff101010 ); Mshadowpaint.setmaskfilter (new blurmaskfilter (8 , BlurMaskFilter.Blur.NORMAL)); ...
Creating objects in advance is a very important optimization tool. The view is drawn very frequently, and it is expensive to create objects that are drawn. Creating a drawing object in the OnDraw () method can significantly reduce the performance of your app and may cause the UI to stall.
Handling Layout Events
In order to draw the view correctly, you first need to know the size of the view. A more complex view often needs to perform multiple layout calculations. You should never assume the size of a view, even if only one app uses your view. Because apps need to handle different screen sizes, different screen densities, and different aspect ratios in both vertical and horizontal modes.
Although view has many methods of measuring size, most of them do not need to be rewritten. If the view does not need to specifically control its size, you only need to rewrite one method: Onsizechanged ().
The Onsizechanged () method is called when the dimension is first allocated, and is called again if the dimension is changed again. Instead of recalculating the view's position, size, and any other dimension-related values in the Onsizechanged () method, we calculate them each time we draw. In the example Piechart, the Onsizechanged () method internally calculates the rectangular border of the pie chart and the relative position of the text and other visual elements.
When a view is assigned a dimension, the layout manager assumes that the dimension contains all of the view's inner margins. So when calculating the dimensions of the view, the inner margin of the view is counted. The following code snippet shows how Piechart.onsizechanged () is done:
//account for padding
float xpad = (float ) (getpaddingleft () + GE Tpaddingright ()); float ypad = (float ) (Getpaddingtop () + Getpaddingbottom ()); //account for the label if (mshowtext) Xpad + = Mtextwidth; float ww = (float ) W-xpad; float hh = (float ) H-ypad; //figure out how big we can make the pie. float diameter = Math.min (ww, hh);
If you want finer control over the parameters of the view layout, implement the Onmeasure () method. The two parameters of this method are view.measurespec. They are used to tell the parent layout of the view how large the view is, whether the view is the largest or only a suggested value, and so on. With optimization, these values are stored in a wrapped integer value, and you must use a static method of View.measurespec to extract the information stored within this integer value.
The following is an example of the Onmeasure () method. In this implementation, Piecart attempts to extend its own area to the size of the internal label.
@Overrideprotected void onmeasure(intWidthmeasurespec,intHEIGHTMEASURESPEC) {//Try for a width based in our minimum intMINW = Getpaddingleft () + getpaddingright () + getsuggestedminimumwidth ();intW = resolvesizeandstate (MINW, Widthmeasurespec,1);//Whatever The width ends up being, ask for a height, this would let the pie //Get as big as it can intMinh = Measurespec.getsize (w)-(int) Mtextwidth + getpaddingbottom () + getpaddingtop ();inth = resolvesizeandstate (Measurespec.getsize (w)-(int) Mtextwidth, Heightmeasurespec,0); Setmeasureddimension (W, h);}
Here are three very important points to watch out for:
- This formula calculates the inner margin of the view. As I said before, this is the duty of view itself.
- The helper Method Resolvesizeandstate () is used to create the final width value and height value. This helper method returns an appropriate VIEW.MEASURESPEC value by comparing the value of view with the spec of the Onmeasure () callback.
- Onmeasure () has no return value. Instead, the method communicates with the outside world by calling the Setmeasureddimension () method. Calling this method is mandatory. If you ignore this call, the view class throws a run-time exception.
Draw
After the object creation code and dimension Measurement code are completed, the OnDraw () method can be implemented next. Each view's OnDraw () method is different, but they still have some of the same features:
- Use the DrawText () method to draw the text. The font type is specified by the Settypeface () method, and the text color is set by the SetColor () method.
- Draw the base drawing through DrawRect (), DrawOval (), and DrawArc (). Change whether the shape is fill or outline mode through SetStyle (), or neither.
- Use the path class to draw more complex graphics. Define the shape by adding lines and curves to the Path object, and then draw the shapes with the DrawPath () method. Just these base shapes can define their path style through the SetStyle () method.
- You can define a gradient fill pattern by creating a LinearGradient object. Call the Setshader () method to populate the shape.
- Draws a bitmap by using the Drawbitmap () method.
For example, the following code is used to draw a piechart. It mixes text, lines, and shapes.
protected void OnDraw(Canvas canvas) {Super. OnDraw (canvas);//Draw the shadowCanvas.drawoval (Mshadowbounds, mshadowpaint);//Draw the label textCanvas.drawtext (Mdata.get (Mcurrentitem) Mlabel, Mtextx, Mtexty, Mtextpaint);//Draw the pie slices for(inti =0; I < mdata.size (); ++i) {Item it = mdata.get (i); Mpiepaint.setshader (It.mshader); Canvas.drawarc (Mbounds, the-It.mendangle, It.mendangle-it.mstartangle,true, Mpiepaint); }//Draw the pointerCanvas.drawline (MTEXTX, Mpointery, Mpointerx, Mpointery, Mtextpaint); Canvas.drawcircle (Mpointerx, Mpointery, Mpointersize, mtextpaint);}
Android Official Development Document Training Series Course Chinese: Create a custom View view drawing