Android custom View series

  • Android custom View Paint draws text and lines
  • Android custom View Precautions
  • Canvas for Android custom View
  • Android custom View image color processing
  • Android custom View dual buffering mechanism and SurfaceView
  • Android custom View invalidate method and postInvalidate method
  • Android custom View Window, View View PL and View of the three processes
  • Android custom View event distribution mechanism summary
  • Android custom View requestLayout method and invalidate method

In the daily development process, the image special effects processing is a very common requirement. In addition to color effects, there are also shape effects, such as rounded corner images, circular images, etc. Today we are going to learn about the shape effects of pictures

Paint Effects

Paint has an API dedicated to image shape effects

//Paint.class
public Xfermode setXfermode(Xfermode xfermode) {
    long xfermodeNative = 0;
    if(xfermode ! = null) xfermodeNative = xfermode.native_instance; nSetXfermode(mNativePaint, xfermodeNative); mXfermode = xfermode;return xfermode;
}
Copy the code

There is only one subclass of Xfermode in Android SDK: PorterDuffXfermode

PorterDuffXfermode controls the blending mode of the image, affecting the display of the intersection area of the two layers.

//PorterDuff.class
public enum Mode {
    /** [0, 0] */
    CLEAR       (0),
    /** [Sa, Sc] */
    SRC         (1),
    /** [Da, Dc] */
    DST         (2),
    /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
    SRC_OVER    (3),
    /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
    DST_OVER    (4),
    /** [Sa * Da, Sc * Da] */
    SRC_IN      (5),
    /** [Sa * Da, Sa * Dc] */
    DST_IN      (6),
    /** [Sa * (1 - Da), Sc * (1 - Da)] */
    SRC_OUT     (7),
    /** [Da * (1 - Sa), Dc * (1 - Sa)] */
    DST_OUT     (8),
    /** [Da, Sc * Da + (1 - Sa) * Dc] */
    SRC_ATOP    (9),
    /** [Sa, Sa * Dc + Sc * (1 - Da)] */
    DST_ATOP    (10),
    /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
    XOR         (11),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
    DARKEN      (16),
    /** [Sa + Da - Sa*Da,
         Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
    LIGHTEN     (17),
    /** [Sa * Da, Sc * Dc] */
    MULTIPLY    (13),
    /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
    SCREEN      (14),
    /** Saturate(S + D) */
    ADD         (12),
    OVERLAY     (15);

    Mode(int nativeInt) {
        this.nativeInt = nativeInt;
    }

    /**
     * @hide
     */
    public final int nativeInt;
}
Copy the code

So what are the effects? Take a look at the renderings below.

Note that Dst represents the bottom layer, also known as the mask layer, and Src is the original

Rounded corner image effect

This is done by superimposing an image layer with rounded corners that are the same size as the image. (1) Initialize the Canvas and brush Paint

Bitmap bitmap = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Copy the code

(2) Draw a layer with rounded corners on the canvas. The layer size is the same as the original image

Canvas. DrawRoundRect (new RectF(0, 0, src.getwidth (), src.getheight ())),80,80, paint);Copy the code

(3) Set the SRC_IN mode for Paint. The SRC_IN mode is the same as the SRC_IN mode

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Copy the code

(4) Draw the image and set the new Bitmap object to the ImageView

canvas.drawBitmap(src, 0, 0, paint);
imageView.setImageBitmap(bitmap)
Copy the code

With the simple steps above, we have the effect of a rounded image.

The mixed display mode we used above is SRC_IN. What if we used SRC_OUT? What do we get?

If you understand the effect shown in the illustration above, I think this problem should not be difficult. The SRC_OUT pattern is the part of the original image that has been removed from the overlay, which in our case is the four rounded corners.

If you don’t quite understand other modes, you can try the above examples to see the actual effect, you can deepen your understanding.

conclusion
  • The key to implementing graphic effects with Paint brush is to set the appropriate overlay effect for the setXfermode() method
  • To understand the overlay effect, you need to understand that before setXfermode() in Paint, the canvas is drawn with the Dst layer in the Mode effect diagram, and after setXfermode(), the canvas is drawn with the Src layer in the Mode effect diagram

Shader

A Shader, also known as a Shader or renderer, is used to implement a series of gradients and renders. There are five types of Shader in Android, They are BitmapShader, LinearGradient, RadialGradient, SweepGradient and ComposeShader r)

In addition, Shader provides several modes for filling

//Shader.class
public enum TileMode {
    /**
     * replicate the edge color if the shader draws outside of its
     * original bounds
     */
    CLAMP   (0),
    /**
     * repeat the shader's image horizontally and vertically */ REPEAT (1), /** * repeat the shader's image horizontally and vertically, alternating
     * mirror images so that adjacent images always seam
     */
    MIRROR  (2);

    TileMode(int nativeInt) {
        this.nativeInt = nativeInt;
    }
    final int nativeInt;
}
Copy the code
  • CLAMP: The most common type of tension
  • -Leonard: REPEAT vertically and horizontally
  • MIRROR: horizontal continuous repeat, vertical continuous repeat
Shder BitmapShader (bitmap)

Unlike the other four types of Shader, BitmapShader produces an image, similar to the image fill gradient in Photoshop. It fills the canvas with a specified Bitmap using Paint.

A common scenario for BitmapShader is to generate circular images

Use BitmapShader to generate circular images

The idea is to fill a circular canvas with images to draw using BitmapShader

(1) Initialize Canvas and Paint

Bitmap bitmap = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
Copy the code

(2) Use Bitmap to generate BitmapShader, and the mode is stretch mode

BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
Copy the code

(3) Set the BitmapShader to Paint for later drawing

paint.setShader(shader);
Copy the code

(4) Use Paint to fill a round Canvas with images. The Canvas calls the drawCircle method

// The radius of the circle is half of the side length of the imagefloatradius = Math.min(src.getWidth()/2, src.getHeight()/2); DrawCircle (src.getwidth ()/2, src.getheight ()/2, radius, paint);Copy the code

With the simple steps above, we have achieved the circular effect of the image

CircleImageView CircleImageView CircleImageView CircleImageView CircleImageView Let’s find out.

public class CircleImageView extends ImageView {
    ...
    
    @Override
    protected void onDraw(Canvas canvas) {
        if (mDisableCircularTransformation) {
            super.onDraw(canvas);
            return;
        }

        if (mBitmap == null) {
            return;
        }

        if(mCircleBackgroundColor ! = Color.TRANSPARENT) { canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint); DrawCircle (mdrawAblerect.centerx (), mdrawAblerect.centery (), mDrawableRadius, mBitmapPaint);if (mBorderWidth > 0) {
            canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
        }
    }
    
    private void setup() {... MBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader. mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); . }... }Copy the code

CircleImageView uses BitmapShader to create circular effects. Interested friends can look for research.

Other fill gradients can be seen literally, so if you’re interested, you can write your own examples to see how they work.

conclusion

  • Paint’s setXfermode and setShader methods are used for shape effects
  • The setXfermode method controls how graphics are superimposed by setting different layer overlay modes, while the setShader method uses the same idea as the image fill gradient in Photoshop to set different fill gradients for Paint
  • Using BitmapShader, you can easily get round image effects

Welcome to follow my wechat public number, and make progress with me every day!