Android原生绘图(七):Canvas状态保存和恢复

734 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

1.Canvas状态保存和恢复

前面已经讲了save和saveLayer,这里对canvas的保存和恢复进行详细的讲解。

Canvas调用了translate、scale、roate、skew、clipRect等操作后,后续的操作都基于变换后的Canvas,都会收到影响,对于后面的操作计算并不方便。

Canvas提供了save、saveLayer、saveLayerAlpha、restore、restoreToCount来保存和恢复状态,有了这些函数,我们可以随时恢复canvas到以前 的状态,不必担心当前的操作是否对画布造成的影响。

2.保存和恢复函数

Canvas提供了很多flag,用于保存对应格式的状态,目前已经废弃,建议使用保存全格式。

2.1 save函数

Save函数保存当前画布的matrix、clip等信息到一个私有栈中,之后调用translate、roate、scale、skew、clipRect等操作,当调用restore或者restoreCount时,save之后对canvas的操作都将被弃用,会从canvas状态栈中取出画布的状态信息进行恢复,返回getSaveCount的值,没有调用过一次save,getSaveCount值为1。

getSaveCount

获取栈中保存的状态信息的个数,计算方式等于save的次数减去restore的次数。

2.2 saveLayer

saveLayerAlpha(@Nullable RectF bounds, int alpha) 
saveLayerAlpha(float left, float top, float right, float bottom, int alpha)
saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint)
saveLayer(@Nullable RectF bounds, @Nullable Paint paint)

savelayer和saveLayerAlpha函数调用时会生成一个新的bitmap用于绘制,后续的操作都不会对原来的Canvas造成影响。调用restore或者resoreToCount()函数之后,新生成的bitmap最终会绘制到Canvas对应的原始Bitmap上,也会从canvas状态栈中获取状态信息,对canvas进行恢复。返回getSaveCount的值,没有调用过一次save,getSaveCount值为1。

saveLayerAlpha和saveLayer的区别只是saveLayerAlpha指定了新生成的bitmap的透明度,所以后面不会过多讲解saveLayerAlpha

2.3 restore、restoreToCount

restore函数:清除当前画布的matrix、clip状态信息,从站定取出保存的状态信息应用到画布,调用restore的次数不能超过save的次数

总结:
restore ,restoreToCount两个函数都是用于恢复画布,restore直接取保存在栈中的栈顶的画布状态进行恢复,restoreToCount:是对restore的封装,可以直接弹栈直到目标位置的画布状态,当saveCount小于1时会报错。

实例代码

canvas.drawRect(100, 100, 400, 400, mPaint);
canvas.save();

mPaint.setColor(Color.GRAY);
canvas.scale(0.5f, 0.5f);
canvas.drawRect(100, 100, 400, 400, mPaint);

canvas.restore();
canvas.drawRect(200, 200, 500, 500, mPaint);

绘制蓝色矩形

将画布缩小为0.5倍

绘制的图形发生缩放

恢复canvas

重新绘制相同大小的矩形,可正常画出

canvas.drawRect(200, 200, 700, 700, mPaint);

canvas.saveLayer(0, 0, 100, 100, null);
canvas.drawRect(300, 300, 800, 800, mPaint);//无法绘制,不在saveLayer生成的bitmap范围

canvas.restore();
canvas.drawRect(0, 0, 100, 100, mPaint);