The purpose of this paper

The purpose of this article is to explain the core of a variety of complex and cool custom view in an article, I hope you can get the designer’s UI effect after reading this article can have a spectrum in mind. Know roughly what you can and can’t do with what API. In fact, 90 percent of the solutions given by designers can be found in these apis.

Color Gradient

  Shader shader = new LinearGradient(100, 100, 500, 500, Color.parseColor("# 007500"),
                    Color.parseColor("#ff3333"), Shader.TileMode.REPEAT);
            paint.setShader(shader);
            canvas.drawRect(100, 100, 500, 500, paint);
Copy the code

Take a look at the effect:

Let’s modify the code to see the differences between the three TileModes.

/ / only you Gradient points can be seen when you draw within three different Shader. The effect of TileMode Shader Shader = new that LinearGradient (200, 200, 400, 400, Color.parseColor("# 007500"),
                Color.parseColor("#ff3333"), Shader.TileMode.REPEAT);
        paint.setShader(shader);
        canvas.drawRect(100, 100, 500, 500, paint);


        Shader shader2 = new LinearGradient(200, 700, 400, 900, Color.parseColor("# 007500"),
                Color.parseColor("#ff3333"), Shader.TileMode.CLAMP);
        paint.setShader(shader2);
        canvas.drawRect(100, 600, 500, 1000, paint);


        Shader shader3 = new LinearGradient(200, 1200, 400, 1300, Color.parseColor("# 007500"),
                Color.parseColor("#ff3333"), Shader.TileMode.MIRROR);
        paint.setShader(shader3);
        canvas.drawRect(100, 1100, 500, 1500, paint);

Copy the code

Similar to RadialGradient SweepGradient, you can search for the effect by yourself, but here is no more introduction, similar. Once you understand the drawing range you can really understand the meaning and effects of the three TileModes

BitmapShader shader

In order to understand shader accurately, it is also necessary to be familiar with the coordinate system. Everything is closely related to the coordinate system and the drawing area. The effect understanding is secondary. First I put a picture of a beautiful woman under the xxhdpi directory

Then we write a code to show the picture to my phone, which is of course xxHDPI’s phone, so that the picture does not zoom and we can understand it easily

 Paint mPaint = new Paint();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly);

        canvas.drawBitmap(bitmap, 100, 50, mPaint);

        canvas.drawBitmap(bitmap, 100, 610, mPaint);


//        Shader shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
//        mPaint.setShader(shader);
//
//        canvas.drawCircle(500, 500, 500, mPaint);
    }
Copy the code

Look at the effect

And then understand Shader

Paint mPaint = new Paint(); @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); DrawBitmap (bitmap, 0, 0, mPaint); Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(shader); canvas.drawCircle(900, 900, 100, mPaint); }Copy the code

Ok, now we say we only want to see Yaya’s face, but we don’t want to see anything else. Since we know that the bitmap area of Yaya is drawn in the upper left corner of the view, and the width and height are 366 and 550, we can roughly estimate that the center of our circle is 180,250, and the radius is about 150

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); DrawBitmap (bitmap, 0, 0, mPaint); Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint.setShader(shader); canvas.drawCircle(180, 250, 150, mPaint);Copy the code

Well, the effect is basically satisfactory, and then we want to see the effect of TileMode? In fact, the effect of tileMode is the same as that of the gradient tileMode mentioned above. The effect can only be seen when the original bitmap is drawn, so we can see the effect of TileMode by enlarging the radius

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); DrawBitmap (bitmap, 0, 0, mPaint); Shader shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint.setShader(shader); canvas.drawCircle(180, 250, 450, mPaint);Copy the code

ComposeShader Blend shader

This is a little bit difficult and responsible, mainly to find the correct way of understanding. Finding the right way to understand it is actually much easier.

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); DrawBitmap (bitmap, 0, 0, mPaint); Shader shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); mPaint.setShader(shader); canvas.drawCircle(183, 275, 183, mPaint);Copy the code

And then I’m going to draw a circle and notice how the coordinates work out, it’s essentially the center of this rectangle. Anyway, apparently the end result should be a round head in the middle of the screen

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); / / the android logo artwork size is 144 * 144 note the Bitmap bitmap2 = BitmapFactory. DecodeResource (getResources (), R.mipmap.ic_launcher_round); Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); Shader composeShader = new ComposeShader(shader, shader2, PorterDuff.Mode.SRC_OVER); mPaint.setShader(composeShader); canvas.drawCircle(102, 72, 72, mPaint);Copy the code

Then take a look at the effect of the blend shader:

Changing different parameters has different effects.

Shader composeShader = new composeShader (Shader, shader2, porterduff.mode.dst_in);Copy the code

Porterduff. Mode has a lot of parameters. You can check the official document to see what effect it is. But ultimately, you have to understand the coordinate system.

ColorFilter Color transform

This is easy to understand, in fact, change the color matrix of the brush, to have a different effect. Like the color of the sun. LightingColorFilter PorterDuffColorFilter ColorMatrixColorFilter, etc.

Take the simplest LightingColorFilter to simulate the lighting effect

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); // Shader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); / / / / the android logo artwork size is 144 * 144 note / / Bitmap bitmap2 = BitmapFactory. DecodeResource (getResources (), R.mipmap.ic_launcher_round); // Shader shader2 = new BitmapShader(bitmap2, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // Shader composeShader = new composeShader (Shader, shader2, porterduff.mode.dst_in); ColorFilter lightingColorFilter = new LightingColorFilter(0x00ffff, 0x000000); mPaint.setColorFilter(lightingColorFilter); Canvas. DrawBitmap (bitmap, 0, 0, mPaint);Copy the code

MaskFilter

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.dly); / / BlurMaskFilter. The Blur parameter value you can try A total of four mPaint. SetMaskFilter (new BlurMaskFilter (50, BlurMaskFilter. The Blur. INNER)); Canvas. DrawBitmap (bitmap, 0, 0, mPaint);Copy the code

At this point, most of the basic effects of custom view is basically finished, and finally we commonly used custom view method is just on this basis, plus drawing text, geometric transformation, property animation. This part can be written by yourself to understand the demo, the subsequent text effects, geometric changes, view cutting, attribute animation are based on this part of the content.