Android高级进阶——绘图篇(八)Canvas与图层(二)

一、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标识的意义和使用范围如下:

image.png

从上面的表格中可以看到,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 Paint();  

        mPaint.setColor(Color.GREEN);  
    }  

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

        canvas.drawColor(Color.RED);  
        canvas.saveLayer(0,0,getWidth(),getHeight(),mPaint,Canvas.MATRIX_SAVE_FLAG|Canvas.HAS_ALPHA_LAYER_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);  

    }  
} 

效果图如下:

image.png

这里在保存Flag时,多了一个Canvas.HAS_ALPHA_LAYER_SAVE_FLAG,表示在新建的画布在合成到上一个画布上时,直接覆盖,不清空所在区域原图像,这个标识这里先忽略,我们后面会具体讲。
效果与原因都是与save()相同,指定保存Canvas.MATRIX_SAVE_FLAG,即canvas的位置信息,当调用canvas.revert()后,原始画布的旋转被恢复。所以再次画图到原始画布上时,是没有旋转的。
我们还是直接来看例子吧,裁剪:
下面我们举个例子来看看

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.drawColor(Color.GREEN);  

        canvas.saveLayer(0,0,getWidth(),getHeight(),mPaint,Canvas.MATRIX_SAVE_FLAG|Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);  
        canvas.clipRect(100,0,200,100);  
        canvas.restore();  

        canvas.drawColor(Color.YELLOW);  
    }  
}

效果图如下:

与上面的例子一样,在saveLayer中也只是保存Canvas.MATRIX_SAVE_FLAG,即canvas的位置信息,之后调用canvas.clipRect(100,0,200,100);将画板裁剪,注意我们在讲解canvas时提到了,无论哪个图层调用canvas的位置变换和裁剪操作,所有的画布都会受到连累,这些连累也只表现在画布以后的绘图上,之前画过的图像不会受到影响。 
所以在clipRect之前画出来的全屏绿色是不受影响的,当restore()以后,canvas只恢复了原始画布的位置信息而原始画布的大小却无法被恢复,所以当再调用 canvas.drawColor(Color.YELLOW),也只能画出来一小块了
注意:在上面的例子中用到了canvas.clipRect(),这个函数是不

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值