前言:
有些话说得坦白
就会变成感慨
有些事总想不开
难免有太多无奈
这一路走来
梦想从未更改
相信真心的付出
就能够活得精彩
把头抬起来
拍拍身上的尘埃
坚守心底的真爱
勇敢相信未来
——巫启贤《相信未来》
系列文章:
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