自定义控件三部曲之绘图篇(十四)——Canvas与图层(二)

本文详细探讨了Android中Canvas的保存标志(FLAG)的意义,包括MATRIX_SAVE_FLAG、CLIP_SAVE_FLAG、HAS_ALPHA_LAYER_SAVE_FLAG、FULL_COLOR_LAYER_SAVE_FLAG、CLIP_TO_LAYER_SAVE_FLAG和ALL_SAVE_FLAG。通过实例解析了每个FLAG如何影响画布的状态,如位置、裁剪和图层合成。此外,还介绍了restore()和restoreToCount(int count)的使用和区别,以及它们如何与不同的FLAG配合恢复画布状态。对于Android自定义控件开发者来说,了解这些概念至关重要。
摘要由CSDN通过智能技术生成

前言:

有些话说得坦白
就会变成感慨
有些事总想不开
难免有太多无奈
这一路走来
梦想从未更改
相信真心的付出
就能够活得精彩
把头抬起来
拍拍身上的尘埃
坚守心底的真爱
勇敢相信未来

                ——巫启贤《相信未来》

 

系列文章:

Android自定义控件三部曲文章索引:http://blog.csdn.net/harvic880925/article/details/50995268

一、FLAG的具体意义

1、FLAG概述

有关save系列函数,在canvas中总共有如下几个:

 

 

public int save()
public int save(int saveFlags)
public int saveLayer(RectF bounds, Paint paint, int saveFlags)
public int saveLayer(float left, float top, float right, float bottom,Paint paint, int saveFlags)
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags)
public int saveLayerAlpha(float left, float top, float right, float bottom,int alpha, int saveFlags)

这段我们先关注前四个,save的两个函数和saveLayer的两个函数;我们知道他们两个不同之处在于saveLayer会新建一个画布,而save函数则不会新建画布;它们都具有Flag标识,这些Flag标识的意义和使用范围如下:

FLAG 意义 适用范围
ALL_SAVE_FLAG 保存所有的标识 save()、saveLayer()
MATRIX_SAVE_FLAG 仅保存canvas的matrix数组 save()、saveLayer()
CLIP_SAVE_FLAG 仅保存canvas的当前大小 save()、saveLayer()
HAS_ALPHA_LAYER_SAVE_FLAG 标识新建的bmp具有透明度,在与上层画布结合时,透明位置显示上图图像,与FULL_COLOR_LAYER_SAVE_FLAG冲突,若同时指定,则以HAS_ALPHA_LAYER_SAVE_FLAG为主 saveLayer()
FULL_COLOR_LAYER_SAVE_FLAG 标识新建的bmp颜色完全独立,在与上层画布结合时,先清空上层画布再覆盖上去 saveLayer()
CLIP_TO_LAYER_SAVE_FLAG 在保存图层前先把当前画布根据bounds裁剪,与CLIP_SAVE_FLAG冲突,若同时指定,则以CLIP_SAVE_FLAG为主 saveLayer()

从上面的表格中可以看到,ALL_SAVE_FLAG、MATRIX_SAVE_FLAG、CLIP_SAVE_FLAG是save()、saveLayer()共用的。而另外三个是saveLayer()专用的;我们一个个来解析下它们的不同之处
在讲解之前,我们先考虑一下,如果让我们保存一个画布的状态,以便恢复,我们需要保存哪些内容呢?
第一个是位置信息,第二个是大小信息;好像除此之外也没什么了。所以,位置信息对应的是MATRIX_SAVE_FLAG,大小信息对应的是:CLIP_SAVE_FLAG,这也就是save\saveLayer所共用的,而另外的三个函数,则是指定saveLayer新建的bitmap具有哪种特性。已经不再是保存画布的范畴了。

2、FLAG之MATRIX_SAVE_FLAG

(1)、save(int flag)与MATRIX_SAVE_FLAG

我们知道canvas.translate(平移)、canvas.rotate(旋转)、canvas.scale(缩放)、canvas.skew(扭曲)其实都是利用位置矩阵matrix实现的,而MATRIX_SAVE_FLAG标识就是指定只保存这个位置矩阵,除此之外的其它任何内容都不会被保存;
我们来举个例子来看下

public class MATRIX_SAVE_FLAG_View extends View {
    private Paint mPaint;
    public MATRIX_SAVE_FLAG_View(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayerType(LAYER_TYPE_SOFTWARE,null);
        mPaint = new Paint();

        mPaint.setColor(Color.GREEN);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.rotate(40);
        canvas.drawRect(100,0,200,100,mPaint);
        canvas.restore();

        mPaint.setColor(Color.YELLOW);
        canvas.drawRect(100,0,200,100,mPaint);
    }
}

我们直接看OnDraw函数,先调用 canvas.save(Canvas.MATRIX_SAVE_FLAG)将canvas的位置矩阵保存起来,然后将画布旋转40度之后,画一个绿色矩形;
然后调用canvas.restore()之后将画布恢复,然后再在同一个位置画一个黄色的矩形。
效果图如下:

 

很明显,在canvas.restore()后,画布的旋转给恢复到了原来了状态。
然后我们再来看看,如果我们给画布裁剪,看还能不能被恢复

 

public class MATRIX_SAVE_FLAG_View extends View {
    private Paint mPaint;
    public MATRIX_SAVE_FLAG_View(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayerType(LAYER_TYPE_SOFTWARE,null);
        mPaint = new Paint();

        mPaint.setColor(Color.GREEN);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.clipRect(100,0,200,100);
        canvas.drawColor(Color.GREEN);
        canvas.restore();

        canvas.drawColor(Color.YELLOW);
    }
}

效果图如下:

 

从效果图来看,我们恢复画布后,把画布全部染成了黄色,但并没有染全屏幕的画布,而只是clip后的一部分,这说明,被裁剪的画布没有被还原!
前面我们说了调用 canvas.save(Canvas.MATRIX_SAVE_FLAG)只会保存了位置矩阵!恢复时,也只会恢复画布的位置信息,有关画布的大小,是不会被恢复的!

(2)、saveLayer()与MATRIX_SAVE_FLAG

同样先来看旋转的例子:

 

 

public class MATRIX_SAVE_FLAG_View extends View {
    private Paint mPaint;
    public MATRIX_SAVE_FLAG_View(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayerType(LAYER_TYPE_SOFTWARE,null);
        mPaint = new Pa
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值