One: What is a Shader
A Shader is called a Shader in 3d software and its function is to color an image. The Shader class is one of Android’s most important graphics transformations. Normally we call Paint’s setShader(Shader Shader) method to pass in the Shader object we create as an argument.
But what is a shader? Specific to do not have computer graphics or art foundation programmers, in fact, or very abstract bad to understand. So literally, coloring is just setting the color of the image that we’re drawing, right? In Paint, the setColor method is used to set the color of the image. Why another Shader? Personally, I prefer to think of a Shader as a set of rules or schemes for setting colors (which can be simply defined as what colors to paint in where). The limitation of our setColor method is that the color is set to a solid color. The Shader can give us a color scheme. For example, if I want to draw an image that starts and ends with a gradient from red to blue, I can use the Shader to specify the color gradient and send it to Paint.
Normally we don’t use the Shader class directly, but use its subclasses. Let’s look at the subclasses:





There are five subclasses, as ComposeShader means composite shader, according to the official documentation. Combining is when two shaders are used together, so it will be explained at the end. Here to BitmapShader xxxGradient, ComposeShader order in practice one by one.


2: BitmapShader
Bitmap shader. To start with a little practice, for example, we usually draw a round avatar in development. This can easily be done using BitmapShader.


mPaint = new Paint(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.xyjy2); BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mRadius = bitmap.getHeight() > bitmap.getWidth() ? bitmap.getWidth() / 2 : bitmap.getHeight() / 2; mPaint.setShader(bitmapShader); . canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);Copy the code

The original picture is compared with the processed one

As shown in the code, this effect can be interpreted as a regular Paint set to the bitmap shader that draws a circle on the Canvas.
A question may arise at this point. Shader can be understood as a set of rules or schemes for setting colors. BitmapShader is based on Bitmap. Bitmap has nothing to do with color. How can we say that BitmapShader is a set of color scheme? And here’s the simple way to think about it. Everything we see on a mobile phone screen is made up of the color values displayed in individual pixels. Therefore, the displayed picture is also composed of the color value of each pixel (such as RGB value). Then, the Bitmap object generated by parsing PNG, JPG and other files also needs to correspond to each color value of each pixel and then display the picture on the screen normally. The BitmapShader is also a set of rules for setting colors, drawing which color values in which locations, and this rule is mainly determined by the Bitmap(that is, the image file you load).


Move on!
We don’t just pass in bitmap objects when we create BitmapShader objects. As follows:


BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, 
                    Shader.TileMode.CLAMP);
Copy the code


So what are those two parameters? Literally stretching mode, the first Shader.TileMode is the display mode on the X axis, and the second is the display mode on the Y axis. Enter the class




Is an enumeration class with three values, CLAMP,REPEAT, and MIRROR, all of which are explained. My understanding is:
  • CLAMP — is stretched edge pixel overlay
  • REPEAT — Horizontal and vertical insufficient placement
  • MIRROR – is the continuous flip MIRROR tiling of the horizontal and vertical gaps
The literal interpretation is still a bit abstract, but you can probably understand the effect.


BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP/REPEAT/MIRROR, Shader. TileMode. CLAMP/REPEAT/MIRROR); canvas.drawRect(0, 0, mWidth, mHeight, mPaint);# mwidth.mheight > 2 times the image width to see the effect
Copy the code



XY:CLAMP



XY:REPEAT



XY:MIRROR



Of course, it is also easy to write a word according to the bitmap shader.


bitmapShader1 = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint.setShader(bitmapShader1); mPaint.setAlpha(50); DrawRect (0, 0, mWidth, mHeight, mPaint); mPaint.setAlpha(255); canvas.drawText("Why don't you take the hook?", 20300, mPaint); canvas.drawText("Collecting the Fifty States of Guanshan", 20600, mPaint); canvas.drawText("Please come to lingyan Pavilion for a while.", 20900, mPaint); canvas.drawText("Like a scholar of all ages.", 20120 0, mPaint);Copy the code


BitmapShader art words

3. That LinearGradient
Linear gradient. Let’s take a look at how to create this class object



It is obvious that lines 1,2 would be classed as class a, and lines 3,4 would be classed as class b. Two classes of constructors, the first four arguments are the same type float, representing the starting coordinates x,y, the end coordinates x,y. The last one, the stretch pattern, has been described above and will not be repeated. The difference is that the fifth and sixth parameters, b, are two int/long colors, color1, which indicates the start and end colors of the gradient; A is two arrays (colors,positions) that we use when we need to specify a number of (relative) gradients between positions other than the beginning and end. So let’s do a little bit more complicated b here.


/** linear gradient * int[] mColors *float[] An array of positions, positions ranging from 0 to 1, that specify colors to be placed at that position. * If null is passed, the gradient changes linearly. */ private int[] mColors = {color.red, color.green, color.blue, color.yellow}; LinearGradient = new LinearGradient(0, 0, 300, 0, mColors, null, Shader.TileMode.CLAMP);  mPaint.setShader(linearGradient); canvas.drawRect(0, 0, 300, 300, mPaint); Canvas. Translate (0330); LinearGradient LinearGradient 1 = new LinearGradient(0, 0,0,300, mColors, null, LinearGradient(0, 0,0,300, mColors, null, Shader.TileMode.CLAMP); mPaint.setShader(linearGradient1); canvas.drawRect(0, 0, 300, 300, mPaint); // translate the canvas. Translate (0,330); LinearGradient LinearGradient 2 = new LinearGradient(0, 0,300,300, mColors, null, LinearGradient(0, 0,300,300, mColors, null, Shader.TileMode.CLAMP); mPaint.setShader(linearGradient2); canvas.drawRect(0, 0, 300, 300, mPaint);Copy the code

Linear gradient

We may need to implement a horizontal progress bar with a gradient in our work. Use the LinearGradient to achieve this.


Four RadialGradient.
Circular gradient.



Since the circular gradient diffuses from point to surface (imagine the effect of a stone ripple on calm water), the above parameters centerX,centerY,radius are easy to understand; Respectively represent the x,y coordinates of the origin and the maximum radius of diffusion. It is not difficult to understand the meanings of the following parameters, which are similar to those described above for linear gradients. Let’s try it out and see how it works.


mRadius = 250; canvas.translate(30, 0); //1. The center of the gradient is in the center of the circle & the start and end values are shown below: RadialGradient RadialGradient = new RadialGradient(mRadius, mRadius, mRadius, color.green, color.red, Shader.TileMode.CLAMP); mPaint.setShader(radialGradient); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); canvas.translate(0, 2 * mRadius + 20); Int [] colors = new int[]{color.yellow, color.green, color.white, color.red};float[] positions = new floatF [] {0.2, 0.3 f, f 0.6, 0.9} f; RadialGradient radialGradient1 = new RadialGradient(mRadius, mRadius, mRadius, colors, positions, Shader.TileMode.CLAMP); mPaint.setShader(radialGradient1); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); canvas.translate(0, 2 * mRadius + 20); RadialGradient radialGradient2 = new RadialGradient(0, 0, mRadius, colors, positions, Shader.TileMode.REPEAT); mPaint.setShader(radialGradient2); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);Copy the code


Ring the gradient

Four SweepGradient.
Scan gradient:



Cx cy is the x and y coordinate of the center of the scan.


SweepGradient swGradient = new SweepGradient(mRadius, mRadius, color.red, color.green); mPaint.setShader(swGradient); canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);Copy the code

Scan the gradient

Five ComposeShader.
Composite shaders.



The first two arguments to the constructor take two shaders. The purpose of the combined shader is to combine the shaderA and shaderB in the specified pattern. Note: the specified modes include Xfermode, Porterduff. Mode and BlendMode added by API29. There will be a dedicated article on the use of Xfermode later. It can be understood as the way that two shaders are combined, which will not be described in detail here.


mPaint = new Paint(); mBitMap = ((BitmapDrawable) getResources().getDrawable(R.mipmap.xyjy2)).getBitmap(); LinearGradient linearGradient = new LinearGradient(0, 0, 500, 800, mColors, null, Shader.TileMode.CLAMP); BitmapShader bitMapShader = new BitmapShader(mBitMap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); composeShader = new ComposeShader(linearGradient, bitMapShader, PorterDuff.Mode.ADD); mPaint.setShader(composeShader); . canvas.drawRect(0, 0, 800, 1000, mPaint);Copy the code



This is a combination of BitmapShader and LinearGradient.



.
So far, Android Shader related knowledge to roughly finish learning, do a simple summary.





Preview: The next article introduces the knowledge related to image filters.