Custom controls the drawing of the trilogy (13)--canvas and layers (i)

Source: Internet
Author: User
Tags drawtext

Foreword: Suddenly know grandmother 79, I am afraid, good want to cry

Series Articles:

Android Custom Control Trilogy Article index: http://blog.csdn.net/harvic880925/article/details/50995268


After explaining the several methods of paint, I felt it necessary to insert a piece of knowledge about canvas canvas, before starting paint, we explained a few articles of canvas drawing and Cavas's Save (), store () knowledge, This is a system supplement to the canvas, and the previous articles are linked as follows:
Drawing of custom Controls (i): Overview and Basic geometry drawing
The drawing of custom Controls (ii): path and text
Drawing of custom Controls (iii): Region (range)
The drawing of custom controls (iv): Canvas transformations and operations

first, how to get a canvas objectmethod One: Override the OnDraw, Dispatchdraw method when customizing the view(1), definitionLet's take a look at the definition of OnDraw and Dispatchdraw methods.

protected void OnDraw (canvas canvas) {    super.ondraw (canvas);} protected void Dispatchdraw (canvas canvas) {    super.dispatchdraw (canvas);}
You can see that OnDraw, Dispatchdraw has a canvas object in the passed in parameter. This Canvas object is the canvas object in view, and the canvas object is used to draw the effect directly into the view.
(2), OnDraw, Dispatchdraw difference
    • OnDraw () means drawing the view itself.
    • Dispatchdraw () is drawing a child view
Both the view and the ViewGroup order are OnDraw ()->dispatchdraw ()
But in ViewGroup, when it has a background, it calls the OnDraw () method, otherwise it skips OnDraw () and calls Dispatchdraw () directly, so if you want to draw in ViewGroup, you tend to override the Dispatchdraw () method
In view, OnDraw () and Dispatchdraw () are all called, so we can get results whether we put the drawing code in OnDraw () or Dispatchdraw (), but because Dispatchdraw () is to draw a child control, so the principle is that when drawing the view control, we are re-ondraw () function
so the conclusion came:
when you draw the view control, you need to override the OnDraw () function, and you need to override the Dispatchdraw () function when you draw viewgroup.
method Two: Create with bitmap1. Construction MethodUse:
Canvas c = new canvas (bitmap);
Or
Where bitmap can be loaded from the picture, can also be created, there are several methods
Method One: Create a new blank bitmapbitmap bmp = Bitmap.createbitmap (width, height Bitmap.Config.ARGB_8888);//Method Two: Load Bitmap bmp from the picture = Bitmapfactory.decoderesource (Getresources (), r.drawable.wave_bg,null);
These two methods are the most common, in addition to these two methods, there are several other methods (such as the construction of a matrix with a copy of the image-the previous example of the reflection image), here is no longer involved, you can go to see the bitmap constructor.
2. Use in OnDraw ()We must note that if we construct a canvas with bitmap, the image drawn on this canvas will be stored on this bitmap, not on the view, and if you want to draw on the view you must use OnDraw (Canvas Canvas) function to draw the canvas over bitmap to the view.
Here's an example:
public class Bitmapcanvasview extends View {    private Bitmap mbmp;    Private Paint Mpaint;    Private Canvas Mbmpcanvas;    Public Bitmapcanvasview (context context, AttributeSet Attrs) {        Super (context, attrs);        Mpaint = new Paint ();        Mpaint.setcolor (color.red);        Mbmp = Bitmap.createbitmap (A. Bitmap.Config.ARGB_8888);        Mbmpcanvas = new Canvas (mbmp);    }    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        Mpaint.settextsize (+);        Mbmpcanvas.drawtext ("Big sb", 0,100,mpaint);    }}
Let's look at the results of the operation:

Can see that the yarn is not, why is it?
Let's take a closer look at the OnDraw function:

protected void OnDraw (canvas canvas) {    super.ondraw (canvas);    Mpaint.settextsize (+);    Mbmpcanvas.drawtext ("Big sb", 0,100,mpaint);}
In the OnDraw function, we just draw the text on the Mbmpcanvas, that is, we create a new mbmp image! This picture doesn't have anything to do with our view. Well, we need to draw the mbmp picture to the view, so we need to add the following sentence in the OnDraw, mbmp to the view
Canvas.drawbitmap (Mbmp,0,0,mpaint);
So the modified code is:
public class Bitmapcanvasview extends View {    private Bitmap mbmp;    Private Paint Mpaint;    Private Canvas Mbmpcanvas;    Public Bitmapcanvasview (context context, AttributeSet Attrs) {        Super (context, attrs);        Mpaint = new Paint ();        Mpaint.setcolor (color.red);        Mbmp = Bitmap.createbitmap (A. Bitmap.Config.ARGB_8888);        Mbmpcanvas = new Canvas (mbmp);    }    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        Mpaint.settextsize (+);        Mbmpcanvas.drawtext ("Big sb", 0,100,mpaint);        Canvas.drawbitmap (Mbmp,0,0,mpaint);    }}
The effect is:

Method Three: Surfaceholder.lockcanvas ()In the operation of the Surfaceview need to use the canvas, the knowledge about the Surfaceview will be opened a separate explanation, here is the first.
second, layer and canvasIn the drawing of custom controls (iv): Canvas transformations and operations, we've talked about the canvas's Save () and restore (), and if you've never seen a classmate, be sure to go back and see it again.
In fact, there are other functions besides save () and restore () to save and restore the canvas state, which we'll take a look at.
1, Savelayer ()Savelayer () has two functions:

/** * Save the canvas content of the specified rectangular area */public int savelayer (RECTF bounds, paint paint, int saveflags) public int Savelayer (float left, F Loat top, float right, float bottom,paint Paint, int saveflags)
    • RECTF bounds: The rectangle of the area to save.
    • int SaveFlags: Values are: All_save_flag, Matrix_save_flag, Clip_save_flag, Has_alpha_layer_save_flag, FULL_COLOR_LAYER_SAVE _flag, Clip_to_layer_save_flag A total of these six, of which all_save_flag means to save all the content, the specific meaning of these signs we will be specific later;
The second constructor is actually the same as the first one, except that a rectangle is constructed from four points.
Let's take a look at an example and get Xfermode to do the experiment and see what Savelayer has done:

public class Xfermodeview extends View {private int width = 400;    private int height = 400;    Private Bitmap dstbmp;    Private Bitmap srcbmp;    Private Paint Mpaint;        Public Xfermodeview (context context, AttributeSet Attrs) {Super (context, attrs);        Setlayertype (view.layer_type_software, NULL);        Srcbmp = makesrc (width, height);        Dstbmp = makedst (width, height);    Mpaint = new Paint ();        } @Override protected void OnDraw (canvas canvas) {super.ondraw (canvas);        Canvas.drawcolor (Color.green);        int layerid = canvas.savelayer (0, 0, Width * 2, Height * 2, Mpaint, Canvas.all_save_flag);        Canvas.drawbitmap (dstbmp, 0, 0, mpaint);        Mpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));        Canvas.drawbitmap (Srcbmp, WIDTH/2, HEIGHT/2, Mpaint);        Mpaint.setxfermode (NULL);    Canvas.restoretocount (Layerid); }//Create a bitmap with a circle, used for the "DST" image static bitmap maKEDST (int w, int h) {Bitmap BM = Bitmap.createbitmap (W, H, Bitmap.Config.ARGB_8888);        Canvas c = new canvas (BM);        Paint p = new paint (Paint.anti_alias_flag);        P.setcolor (0XFFFFCC44);        C.drawoval (New RECTF (0, 0, W, h), p);    return BM; }//Create a bitmap with a rect, used for the "src" image static bitmap makesrc (int w, int h) {Bitmap BM =        Bitmap.createbitmap (W, H, Bitmap.Config.ARGB_8888);        Canvas c = new canvas (BM);        Paint p = new paint (Paint.anti_alias_flag);        P.setcolor (0xff66aaff);        C.drawrect (0, 0, W, h, p);    return BM; }}
This code should be very familiar, this is our example code when explaining Setxfermode (), but before savelayer the entire screen is painted green, as follows:

So the question is, if we get rid of the savelayer, see what happens:

protected void OnDraw (canvas canvas) {    super.ondraw (canvas);    Canvas.drawcolor (color.green);    Canvas.drawbitmap (dstbmp, 0, 0, mpaint);    Mpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));    Canvas.drawbitmap (Srcbmp, WIDTH/2, HEIGHT/2, mpaint);    Mpaint.setxfermode (null);}
This has changed:

I rub the class ... Remove Savelayer () actually the effect is not the same ...
Let's look at the effect of the mode.src_in: when processing the source image, the source image is mainly displayed, and the transparency and saturation of the source image is changed by using the transparent of the target image at intersection. When the target image has a transparency of 0 o'clock, the source image is not displayed at all.
Back to see the result, the first result is right, because the region is not intersected with the transparency of the area is 0, and the second image how to become the cock-like, the source image is all displayed.

(1), Savelayer drawing processThis is because when calling Savelayer, a new bitmap is generated, the size of which is the size of the save area we specify, and the newly generated bitmap is fully transparent. All of the drawing operations are performed on this bitmap after calling Savelayer.
So:
int layerid = canvas.savelayer (0, 0, Width * 2, Height * 2, Mpaint, Canvas.all_save_flag); Canvas.drawbitmap (dstbmp, 0, 0, Mpaint); Mpaint.setxfermode (new Porterduffxfermode (PorterDuff.Mode.SRC_IN)); Canvas.drawbitmap (Srcbmp, WIDTH/2, HEIGHT/2, Mpaint);
We have said that when drawing the source image, all the contents of the previous canvas will be taken as the target image, whereas in the Savelayer newly generated bitmap, only the dstbmp corresponding to the circle, so in addition to the circle and the intersection of the position is empty pixels.
After the drawing is finished, the bitmap generated by the Savelayer will be covered in the original canvas.
So the synthesis of xfermode at this point is as follows:

Savelayer the image on the newly created canvas as the target image, the transparent layer where the rectangle intersects, and the calculated result is drawn on the newly created transparent canvas. Finally, the results are covered directly on the original canvas, resulting in a final display effect.

(2), no Savelayer drawing processThen we look at the second example, in the second example, the only difference is to remove the savelayer;
After the Savelayer is removed, all the drawing operations are placed on the bitmap corresponding to the canvas of the original view.

protected void OnDraw (canvas canvas) {    super.ondraw (canvas);    Canvas.drawcolor (color.green);    Canvas.drawbitmap (dstbmp, 0, 0, mpaint);    Mpaint.setxfermode (New Porterduffxfermode (PorterDuff.Mode.SRC_IN));    Canvas.drawbitmap (Srcbmp, WIDTH/2, HEIGHT/2, mpaint);    Mpaint.setxfermode (null);}
Since we first dyed the whole canvas green, and then drew a circle, so when applying xfermode to draw the source image, the target image of the current bitmap on all the images, that is, the whole green screen and a circle. So this time the source image of the intersection area is not transparent pixels, transparency is all 100%, it is not difficult to explain the result is the reason for this.
The Xfermode synthesis process at this time is as follows:

Because Savelayer is not called, the circle is drawn directly on the original canvas, and when the rectangle intersects, it is calculated directly with all the images on the original canvas.
So the conclusions about Savelayer come to the following:
Savelayer creates a completely new, transparent bitmap that matches the specified saved area, and subsequent drawing operations are placed on this bitmap. After the drawing is finished, it is displayed directly on the bitmap of the previous layer.

2. Canvas and LayerWe've talked about the concept of canvas (Bitmap), layers, and canvas, and we're all going to get dizzy, so let's talk about the relationship below.
layers (layer):Each time the CANVAS.DRAWXXX series function is called, a transparent layer is generated to draw the graphic specifically, such as the transparent layer on which we are drawing the rectangle.
Canvas (bitmap):Each canvas is a bitmap, all the images are painted on the bitmap! We know that each time the CANVAS.DRAWXXX function is called, a dedicated transparent layer is generated to draw the graph, and after the drawing is finished, it is built on the canvas. So if we call five draw functions consecutively, we will generate five transparent layers, which are then shown on the canvas.
There are two types of canvas, the first of which is the original canvas of view, which is passed through the OnDraw (canvas canvas) function, where the canvas in the parameter corresponds to the original canvas of the view, and the background of the control is drawn on this canvas!
The other is a man-made canvas, through Savelayer (), new canvas (bitmap), which artificially creates a new canvas. Especially Savelayer (), once a new canvas is called Savelayer (), all subsequent draw functions are drawn on this canvas, only after the restore (), Resoretocount () function is called, To be drawn back to the original canvas.
Canvas:This concept is more difficult to understand, we can understand canvas as an artboard, bitmap to understand the transparent paper, while the layer is understood as layers, each draw function corresponds to a layer, after a drawing is finished, put on the paper display. and a transparent sheet of paper is superimposed on the artboard and displayed. We know that both the artboard and the paper are clamped together, so when we rotate the artboard, all the paper will rotate! When we cut the entire artboard for hours, the paper will be smaller!
This is very important, when we use Savelayer to generate multiple paper, and then the top of the paper call Canvas.rotate (30) is to rotate the artboard, all the paper is rotated 30 degrees! This is a very important point.
In addition, if the top-level drawing paper calls Canvas.cliprect () to crop the artboard, all the drawing will be cropped. The only action that can be resumed is to call Canvas.revert () to cancel the last action!
However, in the use of canvas drawing and artboard is not the same, the impact of the canvas is only reflected in the future operation, the previously painted image has been displayed on the screen is not affected.
This must be understood and will be used below.
iii. usage in Save (), Savelayer (), Savelayeralpha ()1, the use of SavelayerSavelayer's statement is as follows:
public int Savelayer (RECTF bounds, paint paint, int. saveflags) public int Savelayer (float left, float top, float right, Flo At Bottom,paint Paint, int saveflags)
We mentioned earlier that Savelayer will create a new canvas (bitmap), and all subsequent operations are done on this canvas. Let's take a look at the precautions in using Savelayer separately
(1), all actions after Savelayer are only valid for new canvasLet's look at an example:
public class Savelayeruseexample_3_1 extends view{    private Paint mpaint;    Private Bitmap Mbitmap;    Public Savelayeruseexample_3_1 (context context, AttributeSet Attrs) {        Super (context, attrs);        Mpaint = new Paint ();        Mpaint.setcolor (color.red);        Mbitmap = Bitmapfactory.decoderesource (Getresources (), r.drawable.dog);;    }    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        Canvas.drawbitmap (mbitmap,0,0,mpaint);        int layerid = Canvas.savelayer (0,0,getwidth (), GetHeight (), mpaint,canvas.all_save_flag);        Canvas.skew (1.732f,0);        Canvas.drawrect (0,0,150,160,mpaint);        Canvas.restoretocount (Layerid);    }}
As follows:

In OnDraw, we first drew the puppy's image on the original canvas of the view, then created a new layer with savelayer and then canvas.skew the newly created layer horizontally by 45 degrees. So then the rectangle (0,0,150,160) is chamfered.
It is because all the actions after creating a new canvas are done for the new canvas, not the previous canvas, and it's clear that the canvas's horizontal 45-degree skew only affects the Savelayer's new canvas and doesn't have an impact on the original canvas.

(2), specifying the rectangle size by rect is the new canvas sizeIn the parameters of Savelayer, we can specify a rectangle by specifying a Rect object or specifying four points, and the size of the rectangle is the size of the new canvas, so let's take a look at the following example:

public class Savelayeruseexample_3_1 extends View {    private Paint mpaint;    Private Bitmap Mbitmap;    Public Savelayeruseexample_3_1 (context context, AttributeSet Attrs) {        Super (context, attrs);        Mpaint = new Paint ();        Mpaint.setcolor (color.red);        Mbitmap = Bitmapfactory.decoderesource (Getresources (), r.drawable.dog);        ;    }    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        Canvas.drawbitmap (mbitmap, 0, 0, mpaint);        int layerid = canvas.savelayer (0, 0, +, mpaint, canvas.all_save_flag);        Canvas.drawrect (0, 0, $, mpaint);        Canvas.restoretocount (Layerid);    }}

As follows:


When drawing, we first draw the puppy picture on the original canvas, then create a new transparent canvas of size (0,0,100,100), and then draw a rectangle (0, 0, 500, 600) on this canvas. Since the canvas size is only (0,0,100,100), the rectangle (0, 0, 500, 600) is not fully displayed and can only be displayed (0,0,100,100) canvas-sized portions.
That some students said, NND, in order to avoid the canvas is too small to have problems, I always create a new screen size of the canvas how good, so although there is no problem, but you think that the screen size of the canvas need to how much space, according to a pixel need 8bit storage space, 1024x768 machine, The number of bits used is 1024*768*8=6.2m! So when using Savelayer to create a new canvas, be sure to choose the right size, otherwise your app is likely to be oom.
Note, note: In my example are directly new full-screen canvas, because the writing example is more convenient!!!! But I'm just an example, in the real use, be sure to create the right amount of canvas size Oh!
2, the use of SavelayeralphaSavelayeralpha's statement is as follows:

public int Savelayeralpha (RECTF bounds, int alpha, int. saveflags) public int Savelayeralpha (float left, float top, float RI Ght, float bottom,int alpha, int saveflags)
Compared to Savelayer, one more alpha parameter, to specify the new canvas transparency, the value range is 0-255, can be expressed in 16 oxaa;
The meaning of this function is also to create a new bitmap canvas at the time of invocation, and all subsequent drawing operations will work on this canvas, but the canvas is transparent and transparency is specified by alpha values.
Let's look at an example.
public class Savelayeralphaview extends View {    private Paint mpaint;    Public Savelayeralphaview (context context, AttributeSet Attrs) {        Super (context, attrs);        Mpaint = new Paint ();        Mpaint.setcolor (color.red);    }    @Override    protected void OnDraw (canvas canvas) {        super.ondraw (canvas);        Canvas.drawrect (100,100,300,300,mpaint);        int layerid = Canvas.savelayeralpha (0,0,600,600,0x88,canvas.all_save_flag);        Mpaint.setcolor (color.green);        Canvas.drawrect (200,200,400,400,mpaint);        Canvas.restoretocount (Layerid);    }}
As follows:

After Savelayeralpha, we draw a green rectangle, because the transparency of the new rectangle Savelayeralpha is 0x88 (136) is about 50% transparency, and it can be seen that after the new image is composited with the previous canvas, it is transparent.

Well, this article will be here first, the next one to explain in detail the significance of each flag in the parameters.

If this article has helped you, remember to pay attention to OH

Source: http://download.csdn.net/detail/harvic880925/9510189 (merged with the second corresponding resource in a project)

Please respect the original copyright, reproduced please indicate the source: http://blog.csdn.net/harvic880925/article/details/51317746 Thank you

If you like my article, then you will like my public number, will be regularly pushed to the latest blog articles and collect dry goods to share to everyone (once a week)










Custom controls the drawing of the trilogy (13)--canvas and layers (i)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.