小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
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);