Android Canvas API Detailed Explanation (Part 1)

Introduction to this section:

Previously, we spent 13 sections explaining in detail most of the commonly used APIs of the Paint class in Android. In this section, we will explain some commonly used APIs of Canvas (drawing board).

  • 8.3.1 Detailed Explanation of the Three Drawing Tool Classes
  • Some of the methods we can call have been listed in the following categories:

    • drawXxx method family : Draw a picture in the current drawing area with a certain coordinate value, and the layers will be superimposed, that is, the layer drawn later will cover the layer drawn earlier.
    • clipXXX method family : clip a new drawing area in the current drawing area, and this drawing area is the current drawing area of ​​the canvas object. For example: clipRect(new Rect()), then the rectangular area is the current drawing area of ​​the canvas
    • getXxx method family : Get some values ​​related to Canvas, such as width and height, screen density, etc.
    • Save (), restore (), saveLayer (), restoreToCount () and other methods to save the restored layer
    • translate (translation), scale (zoom), rotate (rotation), skew (tilt)

    Of course, there are other scattered methods. Well, starting from this section, I will pick some interesting APIs to learn~

    And this section first brings you the detailed explanations of translate (translation), scale (zoom), rotate (rotation), skew (tilt) and save (), restore ()!

    Official API documentation: Canvas

    In addition, we must first clarify the directions of the X-axis and Y-axis in Canvas:


1. translate (translation)

Method : translate (float dx, float dy)

Analysis : translation, the coordinate origin of the canvas is moved x to the left and right, and y to the up and down direction. The default position of the canvas is (0,0)

Parameters : dx is the moving distance in the horizontal direction, dy is the moving distance in the vertical direction

Example usage :

for(int i=0; i < 5; i++) {
    canvas.drawCircle(50, 50, 50, mPaint);
    canvas.translate(100, 100);
}

Running effect :


2.rotate (rotate)

方法rotate(float degrees) / rotate(float degrees, float px, float py)

Analysis : rotate degrees around the origin of coordinates, the value is positive clockwise

Parameters : degrees is the rotation angle, px and py are the coordinates of the center point of the specified rotation (px, py)

Example usage :

Rect rect = new Rect(50,0,150,50);
canvas.translate(200, 200);
for(int i = 0; i < 36;i++){
    canvas.rotate(10);
    canvas.drawRect(rect, mPaint);
}

Running effect :

Code analysis :

Here we first call translate(200,200) to move the coordinate origin of the canvas to (200,200), and then draw, so the result of our drawing can be completely displayed on the canvas, if we set (10,200,200 for rotate ), the result would be:

Do you have any doubts? This involves the concept of Canvas multi-layer, and I will talk about it later~


3.scale (zoom)

方法scale(float sx, float sy) / scale(float sx, float sy, float px, float py)

Parsing : Scale the canvas

Parameters : sx is the scaling ratio in the horizontal direction, sy is the scaling ratio in the vertical direction, I don’t know px and py, the decimal is zooming out , and  the integer is zooming in

Example usage :

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.scale(0.8f, 0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

Running effect :


4.skew (tilt)

Method : skew (float sx, float sy)

Analysis : oblique, can also be translated as beveled, twisted

Parameters : sx is the corresponding angle of inclination in the x-axis direction, sy is the corresponding angle of inclination in the y-axis direction, both values ​​are tan values! All are tan values! All are tan values! For example, if you want to tilt 60 degrees in the x-axis direction, then the decimal value corresponds to: tan 60 = square root 3 = 1.732!

Example usage :

canvas.drawBitmap(bmp,0,0,mPaint);
canvas.translate(200, 200);
canvas.skew(0.2f,-0.8f);
canvas.drawBitmap(bmp,0,0,mPaint);

Running effect :


5. The concept of Canvas layer and the detailed explanation of save() and restore()

We generally like to call Canvas a canvas. Children's shoes always think that Canvas is a simple drawing paper, so I would like to ask how to use canvas to complete multi-layer animation? In the example of translate translation above, why drawCircle(50, 50, 50, mPaint); the reference coordinates are always (50,50), so why does this effect appear? Doubtful children's shoes may have been confusing the concept of the screen with the concept of Canvas. Let's restore the crime scene of calling translate:

As shown in the figure, the origin of the canvas coordinates moves 100 on the x and y axes respectively; then what if we want to return to the (0,0) point to draw a new graph? How to break, translate(-100,-100) slowly translate back? It's not really that complicated...

Well, it’s not a secret, we can save the current state of the canvas before doing the translation transformation. In fact, Canvas provides us with the support of layers (Layer), and these Layers (layers) are based on the "stack structure". managed

When we call the save() method, the current state of the Canvas will be saved and added to the Canvas stack as a Layer. In addition, this Layer is not a specific class, but a conceptual thing. !

And when we call the restore() method, the previous state of the Canvas will be restored, and at this time the layer stack of the Canvas will pop up the Layer at the top of the stack, and the subsequent Layer will come to the top of the stack, and the Canvas at this time will return to this stack Canvas state saved when like!

Simply put : save() pushes a Layer onto the stack, and restore() pops a Layer at the top of the stack, which represents the state of the Canvas! That is to say, you can save() multiple times, and you can restore() multiple times, but the number of calls to restore cannot be greater than save, otherwise an error will occur! This is what most people say on the Internet, but there is no such problem in the actual test. Even if I restore more times than save, there is no error. The visual inspection is that the system has been changed. Wait for the next test to show everyone~ 

 Come, come, write an example to verify the role of save and restore!

Write an example :

Example code :

canvas.save(); //Save the state of the current canvas 

canvas.translate(100, 100); 
canvas.drawCircle(50, 50, 50, mPaint); 

canvas.restore(); //Restore the state of the saved Canvas 
canvas .drawCircle(50, 50, 50, mPaint);

Running result :

Needless to say, the code and results have already explained everything, and then we make it more complicated, let's post multiple save() and restore()!

Example code:

canvas.save();

canvas.translate(300, 300);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.rotate(45);
canvas.drawBitmap(bmp, 0, 0, mPaint);
canvas.save();

canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

Running result :

Result analysis :

First translate (300,300) to draw, then rotate 45 degrees to draw, then rotate 45 degrees to draw, and then translate (0,200), during each time before drawing save(), you may have a question here, the last translation is not Why does y move 200, why does it turn to the left? Hey, I will tell you that rotate() rotates the entire coordinate axis? Axis changes:

Well, you understand rotate(), right? That’s fine, then let’s try restore~ We add two restore()s in front of the final drawing!

canvas.restore();
canvas.restore();
canvas.translate(0, 200);
canvas.drawBitmap(bmp, 0, 0, mPaint);

Running result :

Don't say anything, experience it yourself, and add more restore() !

Interesting, come again, continue to add restore()

Well, it seems that we can’t write restore again, because we only saved four times. According to the Internet, this will report an error. Is it true? Here we call a method provided by Canvas to get how many Layers are in the current stack: getSaveCount() ; then add a Log before and after save() and restore() to print out the number of Layers in the stack:

The result is really happy to hear and see. After all, practice brings true knowledge. It may be that Canvas has been modified, or other reasons. Here we need to look at the source code to know. Time is concerned. Here we know that the number of restores can be more than save, but it is still recommended to restore. The number of times is still less than save, so as to avoid unnecessary problems~ As for the process of pushing and popping, I will not talk about it. I draw and draw by myself, which is very easy to understand!


6. saveLayer() and restoreToCount() explanation

In fact, these two methods are similar to save and restore, but there are some more things on the basis of the latter, such as saveLayer(), which has the following overloaded methods:

You can understand that the save() method saves the entire Canvas , while saveLayer() can selectively save the state of a certain area. In addition, we see that there is a: int saveFlags in the meal and accommodation , this is the setting to save That object! Possible values ​​are:

mark illustrate
ALL_SAVE_FLAG save all state
CLIP_SAVE_FLAG Save the state of a cropped region
CLIP_TO_LAYER_SAVE_FLAG Save the state in the preset scope
FULL_COLOR_LAYER_SAVE_FLAG Save Color Coat
HAS_ALPHA_LAYER_SAVE_FLAG opaque layer save
MATRIX_SAVE_FLAG State saving of Matrix information (translate, rotate, scale, skew)

PS: There is something wrong with the above description. The author’s English level is low, and I may have made a mistake. If you know anything, please correct me. Thank you~

Here we write an example to verify: we choose CLIP_TO_LAYER_SAVE_FLAG mode to write an example

Implementation code :

RectF bounds = new RectF(0, 0, 400, 400);
canvas.saveLayer(bounds, mPaint, Canvas.CLIP_TO_LAYER_SAVE_FLAG);
canvas.drawColor(getResources().getColor(R.color.moss_tide));
canvas.drawBitmap(bmp, 200, 200, mPaint);
canvas.restoreToCount(1);
canvas.drawBitmap(bmp, 300, 200, mPaint);

Running result :

About saveLayer(), we will use it later and then explain it in detail~ Here is a general idea~

Then go to this restoreToCount(int) , which is simpler, directly pass in the number of Layers to be restored, jump directly to the corresponding layer, and at the same time kick all the Layers above the layer out of the stack, making this layer a Stack top~! It is much more convenient and quicker than writing multiple restore()~

Guess you like

Origin blog.csdn.net/leyang0910/article/details/131828041