我们在看很多自定义view的源码里经常会有canvas.save()和canvas.restore()出现,今天我们就来看一下canvas为什么要进行这样的操作以及这样的操作的原理.
在我们平时的概念里应该觉得canvas就是我们的屏幕,但是其实不是的,canvas其实应该是一个静态缓冲层,我们在canvas是做完绘画的操作,然后系统将canvas上的图像放置到屏幕上.下面我们举一个例子,具体步骤是首先在canvas上面画一个红色矩形,然后调用canvas.rotate()方法将canvas旋转一定角度后,然后再画一个绿色矩形,如果canvas对应的是我们看到的屏幕的话,那么红色的矩形也应该会跟绿色的一样发生倾斜,下面我们上代码:
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Paint paint_green = generatePaint(Color.GREEN, Style.FILL, 5);
Paint paint_red = generatePaint(Color.RED, Style.STROKE, 5);
Rect rect1 = new Rect(300,10,500,100);
canvas.drawRect(rect1, paint_red); //画出原轮廓
canvas.rotate(30);//顺时针旋转画布
canvas.drawRect(rect1, paint_green);//画出旋转后的矩形
}
代码运行结果如图所示:
我们看到红色的矩形并没有跟随发生旋转,所以说我们的canvas并不是我们看到的屏幕.刚才我们说canvas是一个静态缓冲层,缓冲层已经证明了,那么为什么说是静态的呢?说canvas是静态是因为它发生变换(包括位移,旋转,切割,放缩,斜切)后是不可逆的,假如说我们执行了canvas.translate()方法让canvas向右平移100个像素,那么我们之后对canvas的所有绘画动作都是基于它位移过后的位置.
那么我们如何在一次canvas变换后重新得到初始状态的canvas呢,我们可以使用canvas.save()保存canvas状态,使用canvas.restore()来取回canvas.我们这里主要说的是canvas.save()和canvas.restore()的保存和取回规则.我们可以这样认为,调用canvas.save()方法我们将一个canvas实例放进了一个栈中,调用canvas.restore()方法是将一个canvas实例从栈中取出,我们知道栈的特点是后进先出,所以当我们多次调用canvas.save()方法后,再调用canvas.restore()方法,我们取出的是最后一个存入栈中的canvas实例,如果继续调用canvas.restore()我们得到的是倒数第二个存入栈中的canvas实例.