最近再看自定义View的Canvas的save()、restore()、rotate()等方法的时候,发现网上很多描述都不太准确。于是就自己写个demo研究了下。
canvas相当于是画布,除了可以在canvas上绘图之外,还可以对画布进行变换及裁剪等操作。canvas有很多方法
canvas.rotate():
对画布进行旋转的意思,后面会详细说。
canvas.save():
每次调用save()函数,都会先保存当前画布的状态,然后将其放到特定的栈中。
canvas.restore()
每次调用restore()函数,都会把栈中的画布状态取处理,并按照这个状态恢复当前的画布,然后在这个画布上作画。
为了比较清晰的显示这两个函数的作用,下面我们就举例子来说明
demo例子1
private void onDraw(Canvas canvas){
//将画布颜色填充为红色
canvas.drawColor(Color.RED);
}
运行效果图如下
demo例子2
private void onDraw(Canvas canvas){
//将画布颜色填充为红色
canvas.drawColor(Color.RED);
//裁剪画布
canvas.clipRect(new Rect(100,100,400,400));
//将画布颜色填充为蓝色
canvas.drawColor(Color.BLUE);
}
运行效果图如下
demo例子3
private void onDraw(Canvas canvas){
canvas.drawColor(Color.RED); //将画布颜色填充为红色
canvas.save(); //保存当前画布大小
canvas.clipRect(new Rect(100,100,400,400));
canvas.drawColor(Color.BLUE);
//恢复画布
canvas.restore();
canvas.drawColor(Color.YELLOW); //将画布颜色填充为黄色色
}
运行效果图如下
从上面3个demo例子可以看到:
例子1.
首先将画布填充为红色,此时画布的大小为整个View的大小。
例子2.
首先将画布填充为红色,此时画布的大小为整个View的大小。再将画布裁剪并填充为蓝色。【注意:此时画布大小被裁剪后 变小了,填充为蓝色的只是一小部分区域】
例子3.
首先将画布填充为红色,再将画布状态保存后,裁剪画布并填充为蓝色。最后将画布还原后填充为黄色。【注意,此时画布大小为整个View】
canvas.rotate()
笔者看到不少人在网上介绍该方法时说,是对画布进行旋转,正角度且是顺时针。本人在实践发现并不是这样的。查找相关资料后发现后引用别人的一段话:
Canvas的这个rotate()方法不管是一个参数还是三个参数的那个,从字面上来看旋转的是“画布”,但是我们最好是理解成旋转的是画布的坐标轴。
这样canvas.rotate()方法就好理解了,但是实际写代码中我们习惯性的x轴是横的 x轴的竖的,所以我们可以辅助理解为顺时针旋转坐标轴 等于画布逆时针旋转了。
而在canvas.rotate()结合canvas.save()和canvas.restore()使用时,实际上是对save()是对canvas的坐标轴状态进行保存。也就是说如果调用canvas.rotate()旋转顺时针旋转30°,后调用canvas.save()进行状态保存,那么画布的坐标轴就不在是横平竖直的了,而是倾斜了30°,这与我们的习惯不符合。
所以我们进行canvas.rotate()旋转之前,一般会调用canvas.save()进行保存画布状态。在旋转、绘制等操作完成后,再调用canvas.restore()方法恢复画布状态。