Android custom View: Paint details, androidpaint
In the first article, I learned how to set various attributes using the Paint method, and used the drawxxx () method to draw various simple views. This article mainly gives a detailed understanding of the Paint and gives more detailed and brilliant results.
To get started, the Paint APIs are mainly divided into the following four types:
-Color
-Effect
-Initialization
-DrawText ()-related
Next we will start learning one by one:
1. color:
Three Layers of color are processed when the Canvas is drawn:
1.1 Basic Color:
The Basic Color of pixels varies depending on the rendering content:
The color Filling Method of Canvas is the color of drawColor/RGB/ARGB (), which is directly written in the parameters of the method and set through parameters (as mentioned in the previous section );
The color of drawBitmap () is provided directly by the Bitmap object (as mentioned earlier );
In addition, it is the drawing of graphics and text, and their color needs to be set with the paint parameter (as described below)
1.1.1 set the color directly: 1.1.1.1 setColor (int color)
The get method corresponding to setColor () is getColor ()
1.1.1.2 setARGB (int a, int r, int g, int B)
Like setColor (color), its parameters use a more direct primary color and transparency value. In actual use, which of the following is convenient and convenient for setColor () and setARGB ()?
1.1.2 setShader (Shader shader) Setting Shader
The English word Shader has never been seen before. Its Chinese name is the "coloring tool", which is also used to set the color for painting. The "colorant" is not unique to Android. It is a common concept in the graphic field. The difference between it and directly setting colors is that the colorant sets a color scheme, or a set of coloring rules. After the Shader is set, the color set by setColor/ARGB () is not used for drawing the image and text. Instead, the color in the Shader solution is used.
Note: When Shader is set, the color set by Paint. setColor/ARGB () does not work.
Using Shader in Android rendering does not directly use the Shader class, but uses several subclasses of it. Specifically, there are several LinearGradient RadialGradient SweepGradient BitmapShader ComposeShader:
1.1.2.1 linear gradient of LinearGradient:
Constructor:
LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader. TileMode tile ).
Parameters:
X0 y0 x1 y1: position of the two endpoints of the gradient
Color0 color1 is the color of the endpoint
Tile: A coloring rule outside the endpoint range. Its type is TileMode. TileMode has three optional values: CLAMP, MIRROR, and REPEAT. CLAMP (clip mode ??? I will not translate this term) the color of the endpoint will be continued outside the endpoint; MIRROR is the image mode; REPEAT is the repetition mode. For more information, see the example.
1.1.2.2 RadialGradient radiation gradient
Radiation gradient is easy to understand, that is, the gradient of radiation from the center to the surrounding area
Constructor:
RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, TileMode tileMode ).
Parameters:
CenterX centerY: coordinates of the Radiation Center
Radius: radiation radius
CenterColor: The color of the Radiation Center.
EdgeColor: The color of the radiant edge.
TileMode: color mode outside the radiation range.
1.1.2.3 SweepGradient scan gradient:
Constructor:
SweepGradient (float cx, float cy, int color0, int color1)
Parameters:
Cx cy: scanning center
Color0: the starting color of the scan.
Color1: End color of Scan
1.1.2.4 BitmapShader
Bitmap is used to fill the image or text with Bitmap pixels. Like this:
Constructor:
BitmapShader (Bitmap bitmap, Shader. TileMode tileX, Shader. TileMode tileY)
Parameters:
Bitmap: the Bitmap object used for template creation.
TileX: horizontal TileMode
TileY: vertical TileMode.
1.1.2.5 ComposeShader hybrid shader
That is, the two Shader are used in combination.
This is not suitable for logo images. The following parts use the materials in the original blog
Note: In the above code, I used two BitmapShader as the ComposeShader () parameter, while ComposeShader () does not support two Shader of the same type under hardware acceleration, therefore, you also need to disable hardware acceleration to see the effect.
Constructor: ComposeShader (Shader shaderA, Shader shaderB, PorterDuff. Mode mode)
Parameters:
ShaderA and shaderB: two successive Shader
Mode: the superposition mode of two Shader, that is, how to draw shaderA and shaderB together. Its type is PorterDuff. Mode.
PorterDuff. Mode
PorterDuff. Mode is used to specify the color policy when two images are drawn together. It is an enum. Different modes can specify different policies. "Color policy" means how to determine the color after the source image is drawn to the target image, and for ComposeShader (shaderA, shaderB, mode) the specific method is to draw shaderB on shaderA to obtain a combined Shader.
I have never heard of PorterDuff. Mode, but it is very likely that it will still be confused: "How to combine? Just ...... The two images are superimposed and combined? How can we combine them ?」 Not to mention, there are actually many strategies to combine.
The most intuitive combination strategy is the Mode: SRC_OVER I used in the above example. Its algorithm is very intuitive: as shown in the figure above, the source image is directly placed on the target image. However, in addition to this, there are actually some other combinations. For example, if I change the mode parameter in the preceding example to PorterDuff. Mode. DST_OUT, the result will be blank:
If you change the mode to PorterDuff. Mode. DST_IN, the mask effect will be changed:
Specifically,There are 17 PorterDuff. Mode entries, which can be divided into two types:
1. Alpha Compositing)
2. Hybrid (Blending)
First, Alpha synthesis is actually the algorithm referred to by the word "PorterDuff. "PorterDuff" is not a meaningful phrase, but the name of two people (accurate to the last name ). These two people published a paper describing 12 operations (algorithms) to draw two images together ). The operations described in this paper are all about the calculation of Alpha channels (that is, the so-called "Transparency ").Alpha Synthesis(Alpha Compositing ).
Check the effect. The results directly steal Official Google Documents.
Source and target images:
Alpha synthesis:
The second type is hybrid, that is, the hybrid modes (such as multiply darken lighten) in Photoshop and other graphics software ). This type of operation is the color itself, not the Alpha channel, and does not belong to Alpha synthesis, so it has nothing to do with Porter and Duff, but for convenience, they are also added to PorterDuff by Google. mode.
Official results are still stolen.
Conclusion
It can be seen that the effects of Alpha synthesis are more intuitive, basically, you can use simple verbal expressions to describe their algorithms (at least for opaque source and target images). For example, SRC_OVER indicates "both are drawn, but place the source image above the target image. "DST_IN indicates" only draw the target image and only draw the region where the source image is overlapped 」.
The effect of the mixed classes is relatively abstract. They can only see their coloring algorithms, but cannot see their usage. But it doesn't matter. If you ask your company's designers with these terms, they will be able to tell you a 123 story.
Therefore, the correct method for these modes is:For Alpha synthesis class operations, master them and use them flexibly in actual development. For mixed classes, you just need to remember their names, in this way, when a designer tells you "I want to do this kind of mixed effect" one day, you can immediately know if you can do this. How can you do this?.
In addition, it is recommended that you try PorterDuff. Mode to help deepen your understanding.
Well, these are the detailed descriptions of several Shader.
In addition to using setColor/ARGB () and setShader () to set the basic color, you can also set the ColorFilter for the second layer of the color.
1.2 setColorFilter(ColorFilter colorFilter)
ColorFilter class. Its name is enough to explain its role: Set Color Filtering for painting. Color Filtering means to set a unified Filtering Policy for the drawn content. Then, the Canvas. drawXXX () method filters each pixel and then draws it out.
Set the ColorFilter in the Paint, using the Paint. setColorFilter (ColorFilter filter) method. ColorFilter does not directly use it, but uses its subclass. It has three subclasses: LightingColorFilter porterducolorfilter and ColorMatrixColorFilter.
1.2.1 LightingColorFilter
This LightingColorFilter is used to simulate a simple illumination effect.
The construction method of LightingColorFilter is LightingColorFilter (int mul, int add). The mul and add values in the parameter are the same as the int values in the color value format, where mul is used to multiply the values of the target pixel, add is used to add the target pixel:
A basic LightingColorFilter that is "unchanged", mul is 0 xffffff, and add is 0x000000 (that is, 0). For a pixel, its calculation process is:
Based on this "Basic LightingColorFilter", you can modify other filters. For example, if you want to remove the red color from the original pixel, you can change its mul to 0x00ffff (the red part is 0). The calculation process is as follows:
The specific effect is as follows:
If you want to remove the green color, you can change its mul to 0xff00ff (the green part is 0). The effect is as follows:
The specific effect should be based on the diagram given by the designer.
1.2.2 PorterDuffColorFilter
This porterducolorfilter uses a specified color and a specified PorterDuff. Mode to synthesize the drawn object. Its construction method is porterducolorfilter (int color, PorterDuff. Mode mode). The color parameter is the specified color, and the mode parameter is the specified Mode. It is also PorterDuff. Mode, but unlike ComposeShader, porterducolorfilter acts as a ColorFilter and can only specify one color as the source rather than a Bitmap.
PorterDuff. Mode has been mentioned before, and the use of porterducolorfilter itself is very simple, so I will not talk about it.
1.2.3 ColorMatrixColorFilter
ColorMatrixColorFilter uses a ColorMatrix to process the color. The ColorMatrix class contains a 4x5 matrix:
[ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]
Through calculation, ColorMatrix can convert the pixels to be drawn. For colors [R, G, B, A], the conversion algorithm is as follows:
R’ = a*R + b*G + c*B + d*A + e; G’ = f*R + g*G + h*B + i*A + j; B’ = k*R + l*G + m*B + n*A + o; A’ = p*R + q*G + r*B + s*A + t;
ColorMatrix has some built-in methods for simple conversion. For example, you can useSetSaturation (float sat) is used to set the saturation. You can also set each of its elements to make fine adjustments to the conversion effect. I will not talk about how to set the effect (in fact, I don't know too much ??). If you have any requirements, you can try this library: StyleImageView.
The above is the second layer of color processing for Paint: The color is processed by setColorFilter (colorFilter.
In addition to the basic color settings (setColor/ARGB (), setShader (), and the original color-based filtering (setColorFilter, the last layer of Paint processes the color by setXfermode (Xfermode xfermode). It processes the problem of "when the color encounters View.
1.3 setXfermode(Xfermode xfermode)
"Xfermode" is actually "Transfer mode". Replacing "Trans" with "X" is a shorthand for some Americans. Strictly speaking, Xfermode refers to the combination of the content you want to draw and the content of the Canvas's target position to calculate the final color. However, to put it bluntly, you need to use the drawn content as the source image, take the existing content in the View as the target image, and select a PorterDuff. Mode as the color Processing Solution for the drawn content. Like this:
Xfermode xfermode = new porterduxfermode (PorterDuff. mode. DST_IN );... canvas. drawBitmap (rectBitmap, 0, 0, paint); // paint. setXfermode (xfermode); // sets the Xfermode canvas. drawBitmap (circleBitmap, 0, 0, paint); // circle paint. setXfermode (null); // clear Xfermode in time when used up
It is also PorterDuff. Mode. PorterDuff. Mode has three APIs in Paint. They work in the same way, but they have different purposes:
In addition, from the sample code above, we can see that when Xfermode is created, it is actually its subclass porterduxfermode. In fact, Xfermode only has this subclass. Therefore, you don't need to think much about setting Xfermode. Use porterduduxfermode directly.
In fact, in earlier Android versions, Xfermode has other sub-classes, but other sub-classes are now deprecated, and now only porterduxfermode is left. So its usage seems a bit cool, but it is actually due to historical issues.
Xfermode considerations
Xfermode is easy to use, but there are two points to note:
1. Use Off-screen Buffer)
In essence, if the code in the above example is executed directly, it will not plot the effect in the plot, and the program will not be drawn as the above animation, but will be like this:
According to the logic, we will think that when we draw a circle in the second step, we will calculate the square drawn in the first step together with it. However, in fact, the display area of the entire View is involved in the calculation when the circle is drawn, and the background color of the View itself is not the default transparent color, and it follows a mysterious logic, this not only draws the entire circle range, but also turns black out of the range. Like this:
[Image Upload Failed... Image-1d4860-1516713456529]
To use setXfermode () for normal painting, you must use Off-screen Buffer to draw the content on an additional layer, and then paste the drawn content back to the View. That is:
[Image Upload Failed... Image-73d320-1516713456529]
By using the off-screen buffer, the content to be drawn is drawn separately on the buffer layer, so no strange results will appear in the use of Xfermode. There are two ways to use off-screen buffering:
Canvas. saveLayer ()
SaveLayer () can be used for short-term off-screen buffering. The usage is very simple. Add a line of code before and after the code is drawn, save it before the painting, and restore it after the painting:
Int saved = canvas. saveLayer (null, null, Canvas. ALL_SAVE_FLAG); canvas. drawBitmap (rectBitmap, 0, 0, paint); // paint. setXfermode (xfermode); // sets Xfermodecanvas. drawBitmap (circleBitmap, 0, 0, paint); // circle paint. setXfermode (null); // clear Xfermodecanvas in time when used up. restoreToCount (saved );
View. setLayerType ()
View. setLayerType () is to directly draw the entire View in the off-screen buffer. SetLayerType (LAYER_TYPE_HARDWARE) uses GPU for caching. setLayerType (LAYER_TYPE_SOFTWARE) directly uses a Bitmap for caching.
For Canvas. saveLayer () and View. setLayerType (), I will not elaborate on their meanings and principles here. I may discuss them in a specific phase later.
If you do not have special requirements, you can use the first method.Canvas. saveLayer () is used to set off-screen buffering for higher performance.