Android裁剪画布 clip

我是因为这样的需求才想去裁剪的

Android裁剪画布 clip

想剪出中间那个透明框


学习到了某篇文章(具体源头已不可考),弄出来的效果是这样的

Android裁剪画布 clip

其实一点也不难,我下面给出源代码,有详细的注释

public class ClipView extends View {
    private Paint mPaint;
    private Path mPath;

    public ClipView(Context context) {
        super(context);
        init();
    }

    public ClipView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ClipView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public ClipView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init() {
        setFocusable(true);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(6);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.RIGHT);

        mPath = new Path();
    }

    private void drawScene(Canvas canvas) {
        canvas.clipRect(0, 0, 100, 100);//占用区间

        canvas.drawColor(Color.WHITE);

        mPaint.setColor(Color.RED);
        canvas.drawLine(0, 0, 100, 100, mPaint);

        mPaint.setColor(Color.GREEN);
        canvas.drawCircle(30, 70, 30, mPaint);

        mPaint.setColor(Color.BLUE);
        canvas.drawText("Clipping", 100, 30, mPaint);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.GRAY);//画灰色背景
        canvas.save();

        canvas.translate(10, 10);//画第一幅图
        drawScene(canvas);
        canvas.restore();
        canvas.save();

        canvas.translate(160, 10);//画第二幅图
        canvas.clipRect(10, 10, 90, 90);//1
        canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);//2 取反
        drawScene(canvas);
        canvas.restore();
        canvas.save();

        canvas.translate(10, 160);
        mPath.reset();
        canvas.clipPath(mPath);
        mPath.addCircle(50, 50, 50, Path.Direction.CCW);//增加圆形区域
        canvas.clipPath(mPath, Region.Op.REPLACE);//显示path内容
        drawScene(canvas);
        canvas.restore();
        canvas.save();

        canvas.translate(160, 160);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);//取并集
        drawScene(canvas);
        canvas.restore();
        canvas.save();

        canvas.translate(10, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);//取并集,但是不要交集
        drawScene(canvas);
        canvas.restore();
        canvas.save();

        canvas.translate(160, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);//要第二次,但是第一次占的,他不要
        drawScene(canvas);
        canvas.restore();
    }
}

所以针对我的需求,我可以这样写

public class MyClip extends FrameLayout{
    private static final String TAG = "xbh";

    public MyClip(@NonNull Context context) {
        super(context);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        path = new Path();
        setWillNotDraw(false);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private Path path;

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.BLACK);
        canvas.save();

        int width = getWidth();
        int height = getHeight();

        int radius = width >> 2;
        int x = width >> 1;
        int y = 5 * radius / 2;

        canvas.clipRect(0,0,width,height);

        path.reset();
        canvas.clipPath(path);
        path.addCircle(x, y, radius, Path.Direction.CCW);
        canvas.clipPath(path, Region.Op.REPLACE);
        canvas.drawColor(Color.parseColor("#FFFFFF"));
        canvas.restore();
        canvas.save();
    }
}

效果如下

Android裁剪画布 clip

源代码如下

public class MyClip extends FrameLayout{
    private static final String TAG = "xbh";

    public MyClip(@NonNull Context context) {
        super(context);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        path = new Path();
        setWillNotDraw(false);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyClip(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private Path path;

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.BLACK);
        canvas.save();

        int width = getWidth();
        int height = getHeight();

        int radius = width >> 2;
        int x = width >> 1;
        int y = 5 * radius / 2;

        canvas.clipRect(0,0,width,height);

        path.reset();
        canvas.clipPath(path);
        path.addCircle(x, y, radius, Path.Direction.CCW);
        canvas.clipPath(path, Region.Op.REPLACE);
        canvas.drawColor(Color.parseColor("#FFFFFF"));
        canvas.restore();
        canvas.save();
    }
}