自定义组件重写onDraw()方法,Canvas类中的saveLayout()、save()、restore()方法

本文详细介绍了如何在自定义Android组件的onDraw方法中,通过saveLayer()和PorterDuff.Mode.CLEAR实现复杂的图层叠加,包括红色背景、蓝色矩形及透明抠图技巧。作者展示了从基本的矩形绘制到使用save/restore操作的逐步过程,帮助读者理解Android Canvas的图层概念和管理机制。

自定义组件重写onDraw方法,内容如下

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint paint = new Paint();
    paint.setColor(Color.RED);
    RectF rectF = new RectF(100, 100, 400, 400);
    canvas.drawRect(rectF, paint);
}

此时画出来的红色矩形(父布局的背景是白色)

我们再调小一点矩形的范围,再画一个小一点的蓝色矩形

        //再画一个小一点的蓝色的矩形
        paint.setColor(Color.BLUE);
        rectF.set(150, 150, 350, 350);
        canvas.drawRect(rectF, paint);

emmmm,我想在蓝色的矩形中间抠出一个小的矩形,让他露出红色的底色,利用PorterDuff.Mode.CLEAR

        //扣出蓝色矩形中的一块区域
        rectF.set(200, 200, 300, 300);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRect(rectF, paint);

what?黑色的?,连白色的背景也没了?因为现在是在同一个canvas中操作的,这一层的东西都会受影响,有点像是Photoshop中的图层概念。那只想让他抠掉蓝色的那一层怎么办?在画好红色的矩形后调用saveLayer()方法来保存当前图层和新建一个图层,然后再画一个蓝色的矩形,再抠出中间的位置,上代码:

        Paint paint = new Paint();
        paint.setColor(Color.RED);
        RectF rectF = new RectF(100, 100, 400, 400);
        canvas.drawRect(rectF, paint);

        //画好红色的矩形后保存图层
        canvas.saveLayer(null, null);

        //再画一个小一点的蓝色的矩形
        paint.setColor(Color.BLUE);
        rectF.set(150, 150, 350, 350);
        canvas.drawRect(rectF, paint);

        //扣出蓝色矩形中的一块区域
        rectF.set(200, 200, 300, 300);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRect(rectF, paint);

效果:

saveLayer有两个参数,第一个参数是一个RectF类,你可以用这个类来指定保存的canvas的位置和大小

啊?这是什么操作,先保存蓝色矩形左上角的位置试试看,改一下刚刚到saveLayer()方法,贴一下全部代码:

        Paint paint = new Paint();
        paint.setColor(Color.RED);
        RectF rectF = new RectF(100, 100, 400, 400);
        canvas.drawRect(rectF, paint);

        //画好红色的矩形后保存图层
        rectF.set(150,150, 250, 250);
        canvas.saveLayer(rectF, null);

        //再画一个小一点的蓝色的矩形
        paint.setColor(Color.BLUE);
        rectF.set(150, 150, 350, 350);
        canvas.drawRect(rectF, paint);

        //扣出蓝色矩形中的一块区域
        rectF.set(200, 200, 300, 300);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRect(rectF, paint);

效果:

emmmmm,去掉抠颜色的代码看看

        //扣出蓝色矩形中的一块区域
//        rectF.set(200, 200, 300, 300);
//        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
//        canvas.drawRect(rectF, paint);

再运行的效果:

到这里就能理解了,用saveLayer()保存了蓝色那一小块的地方,同时新创建的一张canvas大小也是只有蓝色矩形那一小块,所有只能操作这一小块了,还有restore()方法可以恢复上一个canvas,canvas是由一个栈去管理,drawXXX()操作的是栈顶的canvas,画一张图方便理解

----------------------------------------------------------

还有save()方法,这个方法是用来保存坐标系等状态的,这些状态也是由一个栈去管理。当你画好一个图形后,画另一个图形需要对坐标系进行旋转操作和改变画笔颜色,画完后再画别的图形又要把画笔和坐标系的角度调回来,这时save()方法就派上用场了,在你画好第一个图形后调用save()方法可以保存好当前的状态,再去调画笔颜色和坐标系角度去画另一个图形,画好后再调用restore()方法就可以恢复之前的画笔状态和坐标系状态。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值