Custom View in Android --- advanced (Canvas usage)

Source: Internet
Author: User

Custom View in Android --- advanced (Canvas usage)
I. Preface

So today, let's take a look at an article on the UI in Android, how to customize the View advanced article, and a previous article on the prelude, in this article, I mainly introduced some basic knowledge about custom views, and explained painting, Canvas, Path, gradient, and other technologies. After six months, let's take a look at how to use Canvas to customize more special effects at the previous level? Here, I would like to say a few more words, that is, there are still many advanced UI knowledge points in Android. If you have a thorough understanding of UI technology, the treatment is also very good, now we can see that some companies are looking for Android senior UI engineers to ask you to do some cool UIS, and you also need to know a lot about performance, because we know the cool UI animation or something, in fact, if the processing is not good, it will cause a lot of performance problems for the entire program. So I am very interested in the UI and reverse fields in Android.

Ii. Knowledge Point & Implementation Effect

Next let's take a look at how to use Canvas to do some of the effects we often use:

1. Modify the image transparency

2. layer superposition effect (mask layer)

3. Save and restore the canvas

4. Use a matrix to implement translation, rotation, and scaling Animation

5. implement animation by rotating, translating, and scaling the canvas

6. Crop the canvas

There are a total of six knowledge points. After talking about these knowledge points, most of the views on the market now know the principle and can be drawn by yourself. I will write another article about the custom ViewGroup series (LinearLayout, (RelativeLayout.

Iii. Implementation

The following uses examples to describe the above six features. First, let's review how to customize a View. In fact, it is very simple. We only need to integrate the View class, then, in the onDraw method, get a Canvas object and draw various effects we want.

public void onDraw(Canvas canvas)

Let's take a look at the first knowledge point:

1. Modify the image transparency

/*** Modify the argb value of the image * @ param sourceImg * @ param number * @ return */public static Bitmap getTransparentBitmap (Bitmap sourceImg, int number) {int [] argb = new int [sourceImg. getWidth () * sourceImg. getHeight ()]; sourceImg. getPixels (argb, 0, sourceImg. getWidth (), 0, 0, sourceImg. getWidth (), sourceImg. getHeight (); // obtain the ARGB value of the Image number = number * 255/100; for (int I = 0; I <argb. length; I ++) {argb [I] = (number <24) | (argb [I] & 0x00FFFFFF);} sourceImg = Bitmap. createBitmap (argb, sourceImg. getWidth (), sourceImg. getHeight (), Bitmap. config. ARGB_8888); return sourceImg ;}

In the onDraw method, we can draw the modified image:

BitmapDrawable drawable = (BitmapDrawable) ctx. getResources (). getDrawable (R. drawable. cm_whatsapp_ico_audio); Bitmap bitmap = drawable. getBitmap (); // modify the argb value of an image using bitmap = getTransparentBitmap (bitmap, 10); canvas. drawBitmap (bitmap, 0, 0, paint );
The code is actually very simple, it is to get the Bitmap of the source image, and then construct a new image, but at this time we will see the technical points here:

First, we can obtain the ARGB array value of an image. The array size is the pixel value of the image, so each pixel is an int value:

A Indicates transparency: 8 bits

RGB represents the color values of the three colors: 8 bits each

The total length is 32 bits, which is exactly the length of the int type.

When constructing an image, we can see the meaning of Bitmap. Config. ARGB_8888. Of course, this Config has other values, such:

Bitmap. Config. ALPHA_8: only the transparency value is 8 bits, so we can use the byte type. We can imagine a picture without color.

Bitmap. config. ARGB_4444: similar to ARGB.8888, it occupies a different number of digits. Here it is 4*4 = 16 bits. You can use the short type. It can be seen that although ARGB.8888 can display more HD images, however, memory usage is high.

Bitmap. Config. RGB_565: only the color value, no transparency, the number of occupied digits: 5 + 6 + 5 = 16 bits. Use the short type.

The new argb value can be passed when constructing a Bitmap. This means that we can change the transparency and color of the image at will. Let's take a look at the effect:


Let's change his color value as needed:

for (int i = 0; i < argb.length; i++) {argb[i] = (number << 24) | (argb[i] & 0x00FFFFFF);argb[i] = 400 + (argb[i] & 0xFF00FFFF);}

Let's take a look at the effect:

Knowledge point:

1> we can use the getPixel method of Bitmap to obtain the pixel value of an image.

2> understand the meaning of the pixel value of the image and the differences between different configurations.

3> modify the transparency and color of an image.

2. layer superposition effect (mask layer)

We have already introduced this knowledge point. For example, how to create a rounded corner image is done by using the mask layer. In fact, the mask layer is white, that is, how to overlay two images, similar to the ppt, you can choose the upper layer as well as the bottom layer. However, the effects of the mask layer here will be more. Let's take a look at the code implementation below:

// Method for obtaining the rounded corner image/*** android. graphics. porterDuff. mode. SRC: only draw the source image android. graphics. porterDuff. mode. DST: only draw the target image android. graphics. porterDuff. mode. DST_OVER: Draw the target image android at the top of the source image. graphics. porterDuff. mode. DST_IN: Draw the target image android only in the place where the source image and the target image intersect. graphics. porterDuff. mode. DST_OUT: Draw the target image android only when the source image and the target image do not match. graphics. porterDuff. mode. DST_ATOP: Draw the target image at the intersection of the source image and the target image android. graphics. porterDuff. mode. SRC _ OVER: Draw the source image android at the top of the target image. graphics. porterDuff. mode. SRC_IN: draws the source image android only when the source image and the target image are at the intersection of the source image. graphics. porterDuff. mode. SRC_OUT: Draw the source image android only when the source image and the target image do not match. graphics. porterDuff. mode. SRC_ATOP: Draw the source image where the source image and the target image intersect, and draw the target image in different places. android. graphics. porterDuff. mode. XOR: Draw them wherever the source and target images overlap, and do not draw any content in the non-overlapping places. android. graphics. porterDuff. mode. LIGHTEN: obtains the brightest pixels in the two images at each position and displays android. graphics. porterDuff. mode. DARKEN: Get each Two locations on the two images of the most dark pixels and display android. graphics. porterDuff. mode. MULTIPLY: MULTIPLY two pixels at each position by 255, and then use this value to create a new Pixel for display. Result color = Top color * bottom color/255 android. graphics. porterDuff. mode. SCREEN: Invert each color, perform the same operation (multiply and divide them by 255), and then reverse again. Result color = 255-(255-top color) * (255-bottom color)/255) * @ param bitmap * @ param roundPx * @ return */public static Bitmap getRoundedCornerBitmap (Bitmap bitmap, float roundPx) {Bitmap output = Bitmap. createBitmap (bitmap. getWidth (), bitmap. getHeight (), Bitmap. config. ARGB_8888); Canvas canvas = new Canvas (output); final int color = 0xff0000242; final Paint paint = new Paint (); final Rect rect = new Rect (0, 0, bitmap. getWidth (), bitmap. getHeight (); final RectF rectF = new RectF (rect); paint. setAntiAlias (true); canvas. drawARGB (0, 0, 0, 0); paint. setColor (color); canvas. drawRoundRect (rectF, roundPx, roundPx, paint); paint. setXfermode (new porterduxfermode (PorterDuff. mode. XOR); canvas. drawBitmap (bitmap, rect, rect, paint); return output ;}
Here we can see that we can create a canvas first, but the canvas cannot be empty. We need a base chart and use Bitmap to configure it directly. config. the ARGB_8888 configuration creates a white image of the same size as the source image. Of course, we can use the method described above to create an image with transparency and color values and paste it on the canvas. Here we can also directly use the canvas to set the value of ARGB, where all values are 0. At this time, we can paint the image. After we draw a rounded rectangle, we need to set the Mask Layer Effect of the paint brush. Here is the key point. There are many options for the mask layer:
Android. graphics. porterDuff. mode. SRC: only draw the source image android. graphics. porterDuff. mode. DST: only draw the target image android. graphics. porterDuff. mode. DST_OVER: Draw the target image android at the top of the source image. graphics. porterDuff. mode. DST_IN: Draw the target image android only in the place where the source image and the target image intersect. graphics. porterDuff. mode. DST_OUT: Draw the target image android only when the source image and the target image do not match. graphics. porterDuff. mode. DST_ATOP: Draw the target image at the intersection of the source image and the target image android. graphics. porterDuff. mode. SRC_OVER: Draw the source image andro at the top of the Target Image Id. graphics. porterDuff. mode. SRC_IN: draws the source image android only when the source image and the target image are at the intersection of the source image. graphics. porterDuff. mode. SRC_OUT: Draw the source image android only when the source image and the target image do not match. graphics. porterDuff. mode. SRC_ATOP: Draw the source image where the source image and the target image intersect, and draw the target image in different places. android. graphics. porterDuff. mode. XOR: Draw them wherever the source and target images overlap, and do not draw any content in the non-overlapping places. android. graphics. porterDuff. mode. LIGHTEN: obtains the brightest pixels in the two images at each position and displays android. graphics. porterDuff. mode. DARKEN: obtains the lowest pixel in the two images at each position and displays android. grap Hics. PorterDuff. Mode. MULTIPLY: MULTIPLY two pixels in each position by 255, and then use this value to create a new Pixel for display. Result color = Top color * bottom color/255android. graphics. PorterDuff. Mode. SCREEN: Invert each color, perform the same operation (multiply them by 255), and then reverse again. Result color = 255-(255-top color) * (255-bottom color)/255)

 

These options are comprehensive and can achieve any effect of overlapping two images. After setting the paint brush mask layer of the base image, draw the second image, that is, the original image. After the painting is complete, return the base image directly.

Let's take a look at the effect:


 

As you can see, the selection of the mask layer is Mode. XOR. It's really interesting that the values are outside the intersection of the two. Next we will use Mode. SCR_IN to look at it. Unlike Mode. XOR, we will only draw the intersection of the two images:

Well, this achieves the rounded corner of the image. Haha, of course there are other effects of the mask. You can try it and it is also very fun.

Knowledge point:

1> manually create a Bitmap and Canvas

2> understand the mask layer technology to change the overlapping effect of the two images

3. Save and restore the canvas

This technology is also very important when we use the most custom View. To put it bluntly, we will first draw a graph on the canvas, save it, draw a graph, and then restore it. In this way, you can draw different styles on a canvas. Let's take a look at the code below:

/*** Retain Layer Technique ** @ param canvas */public static void saveCanvas (Canvas canvas) {// draw a line first, Paint = new paint (); Paint. setColor (Color. BLUE); paint. setStrokeWidth (10); canvas. drawLine (100,100, paint); // Save the canvas and set the area l, t, r, and bcanvas. saveLayerAlpha (10, 10,300,300, 0x88, Canvas. ALL_SAVE_FLAG); // draw the circle Paint paint1 = new Paint (); paint1.setColor (Color. RED); paint1.setStrokeWidth (10); paint1.setStyle (Paint. style. FILL); canvas. drawCircle (140,140,100, paint1); canvas. restore ();}
We can see that first, we draw a blue line, and then we save the canvas status. When we save it, we can set the canvas area and transparency at the same time, then draw a red circle and restore the canvas. Let's take a look at the effect:


 

First, the Red Circle overlaps with the Blue Line, and the red picture is above. Secondly, we can see that the Red Circle is transparent, not all red. In this way, we learned to save the canvas and restore the canvas state, but in the actual process, we cannot do this simply. Let's change the code and let the canvas translate:

Here we use a matrix to perform canvas translation, and then let's take a look at the effect:

Okay, you see it? When the circle moves, it is actually not the circle, but the canvas moves. Therefore, you must understand the true meaning of the storage and restoration of the canvas:

Each Canvas is created with a default layer. When we use the save method, we create a layer and draw it. When we call the restore method, it is equivalent to the superposition of two layers, so it seems that the canvas is moving. Actually it is not. A new layer is created, and the canvas cannot be moved. In general, the canvas is equivalent to the canvas, and the layer is equivalent to the canvas.

Of course, we also see that the circle is not fully displayed. This is the area we set when saving the canvas. In fact, the area and transparency are the size and transparency of the new layer, this circle is drawn on the new layer, so it will be cropped.

Note the following:

Every time we want to operate the canvas, we must remember one principle:

First, operate the canvas.

If the order is reversed, the operation will have no effect. For example, if the translation effect above is placed behind the drawing circle, there will be no effect.

Knowledge point:

1> use the canvas storage technology to draw the desired special effect

2> understand the canvas translation, scaling, and other effects. Instead of operating the canvas in the true sense, you can create a new layer and then overlay the layers.

3> operate the canvas using a Matrix

4. Use a matrix to implement translation, rotation, and scaling

When implementing simple translation, rotation, scaling, and other functions of the View, Android provides many options, such as traditional animation and attribute animation. However, let's take a look at it today. When we plot images, we use matrices to achieve these effects. When learning linear mathematics, we know that two matrices can be multiplied to achieve various changes. At the same time, A * B = C, A matrix is understood as the matrix before the change, and B matrix is understood as the change matrix, the C matrix is interpreted as a matrix after change. Of course, the Api provided by Android does not require manual computation. Instead, it helps us encapsulate the effect matrix of the three functions: translation, rotation, and scaling, we can also implement manual matrix calculation, but we will not introduce it here, because the matrix operation is still very complicated. If you are interested, you can search for it online. Let's take a look at the code below:

/*** Use Matrix to rotate images * @ param bitmap * @ return */public static Bitmap operateBitmap (Bitmap bitmap) {Bitmap output = Bitmap. createBitmap (bitmap. getWidth (), bitmap. getHeight (), Bitmap. config. RGB_565); Canvas canvas = new Canvas (output); Matrix matrix = new Matrix (); matrix. postRotate (300); matrix. postScale (0.4f, 0.5f); matrix. postTranslate (100,100); canvas. drawBitmap (bitmap, matrix, new Paint (); return output ;}
Here we are still, first create a canvas and base image, and then use the Matrix to operate the image. Here we first rotate, zoom, and pan, and then let's take a look at the effect:

 


We can see that the image looks like this, but here we can see how one is black, because the image configuration we set when creating the base chart is:

Bitmap. Config. RGB_565

This style has no transparency and is black by default.

There is a difference between Matrix operations in Matrix operations, because Matrix multiplication does not support the exchange law. Methods Starting with post are all multiplication, which is our normal operation effect, the method starting with pre is premultiplication. modify the code:

See the results:

I don't know what it turns into. Why do I need to mention the difference between premultiplication and postmultiplication? In fact, I want to explain the following problem:

Do not consider premultiplication and postmultiplication as opposite operations.

If you want to perform the opposite operation, you only need to write the value into a negative value.

Knowledge point:

1> learned matrix operations

2> understand the difference between multiplication before and after a Matrix

5. implement animation by rotating, translating, and scaling the canvas

For more information, see the basic section of the custom View. But here we will use the canvas selection method to achieve the animation effect. The code below is as follows:

 

/*** Rotate the image by rotating the canvas * @ param Canvas * @ param bitmap * @ param argee */public void recyleRotateBitmap (canvas, Bitmap bitmap, int argee) {// it must be noted that the canvas can be drawn only after the canvas is operated. Otherwise, the canvas is ineffective. rotate (argee); Rect rect1 = new Rect (0, 0, bitmap. getWidth (), bitmap. getWidth (); Rect rect2 = new Rect (0, 0, bitmap. getWidth (), bitmap. getHeight (); canvas. drawBitmap (bitmap, rect1, rect2, new Paint (); postInvalidateDelayed (200 );}
Here we can see that the Canvas itself also has the methods of translation, rotation, and scaling, which can be implemented without the need for a matrix. Here we implement a simple principle: it is to change the rotation angle in the onDraw method, then draw a new image, and then call the postInvalidateDelayed method to update the canvas content. Our code in the onDraw method is as follows:


Let's take a look at the effect:

That is, the image starts to rotate along the point in the upper left corner.

Knowledge point:

1> operate the Canvas using the Canvas api

6. Crop the canvas

Sometimes we may need to crop the canvas, that is, to crop the image that has been drawn on the canvas. We only want a part of the image. At this time, we can use the cropping technology to achieve it, for example, if we want to crop an image into an irregular shape, let's look at the Code:

 

/*** Crop the canvas * @ param Canvas * @ param bitmap */public static void clipCanvas (canvas, Bitmap bitmap) {canvas. drawColor (Color. GRAY); // cut the canvas first and draw the content in the canvas. // canvas. clipRect (0, 0,200,200); Path path = new Path (); path. lineTo (0, 0); path. lineTo (400, 0); path. lineTo (100,300); path. lineTo (0, 0); canvas. clipPath (path); Rect rect1 = new Rect (0, 0, bitmap. getWidth (), bitmap. getWidth (); Rect rect2 = new Rect (0, 0, bitmap. getWidth (), bitmap. getHeight (); canvas. drawBitmap (bitmap, rect1, rect2, new Paint ());}
Here we use Path to draw irregular shapes. Here, we need to note that cropping the canvas is also an operation canvas, so we still need to follow a principle:

 

First, operate the canvas.

Let's take a look at the effect:


We can see that path can be used to draw irregular images, and the cropping api also supports regular image cropping, for example: circle, rectangle, and Other Cropping shapes.

Knowledge point:

1> Use Path to draw irregular Images

2> crop the image shape at will

Iv. Knowledge Point Summary

Here we have finished some operations on the Canvas. These operations can meet our needs in daily life. Next we will sort out the learned knowledge points:

1> we can use the getPixel method of Bitmap to obtain the pixel value of an image.
2> understand the meaning of pixel values and the differences between different configurations.
3> modify the transparency and color of an image.
4> manually create a Bitmap and Canvas
5> understand how the mask layer technology changes the superposition of the two images
6> use the canvas Saving Technology to draw the desired special effect
7> understand the effects of canvas translation and scaling, instead of operating the canvas in the true sense. Instead, create a new layer and stack the layers.
8> operate the canvas using a Matrix
9> learned matrix operations
10> understand the difference between multiplication and multiplication of Matrices
11> use the Canvas api to operate the Canvas
12> Use Path to draw irregular Images
13> crop the image shape at will

V. Summary

This article mainly introduces how to operate the canvas to achieve the desired effect of custom View. These APIs do not need to be remembered, but these knowledge points can be remembered, because when we see a UI effect, we can think of these features. If you have nothing to do, let's take a look at some UI effects and special effects, and think about how to implement it, this is very helpful for us to draw the UI. It is useful to make up your mind when it's okay.

Related Article

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.