Android — 自定义View(三)之画布操作

前言

同样的,我们回顾一下上一篇所学的知识,讲解了线段、圆、扇形、圆弧等等的基本图形的绘制。最后实现了一个饼状图,还是很有成就感的。不知道你有没有注意到,在绘制饼状图的时候,我们把坐标原点移动到了屏幕中心,其实这就是画布操作的一种,那下面我们就着重讲解一下画布操作。

合理的使用画布操作可以帮你用更加容易理解的方式去实现你要的效果,这也是画布操作存在的原因。所有的画布操作都只影响后续的绘制,对之前已经绘制的内容没有影响。

目录如下:

  1. 位移(translate)
  2. 缩放(scale)
  3. 旋转(rorate)
  4. 错切(skew)
  5. 快照(save)和回滚(restore)

抱紧我的大腿!

位移(translate)

位移移动的是画布的坐标原点,位移是基于当前位置移动,而不是屏幕左上角。

1
canvas.translate(dx, dy);

缩放(scale)

缩放提供了两个方法,如下:

1
2
public void scale (float sx, float sy)
public final void scale (float sx, float sy, float px, float py)

两个方法中前两个参数分别表示在X轴和Y轴的缩放比例,而第二种方法多了两个参数,这两个参数是用来控制缩放中心位置的,相当于中心点的translate(位移)。

缩放比例(sx,sy)的取值范围:

取值范围 ( n ) 说明
[-∞,-1) 先根据缩放中心放大n倍,再根据缩放中心轴进行翻转
-1 根据缩放中心轴进行翻转
(-1,0) 先根据缩放中心缩小到n,再根据中心轴进行翻转
0 不会显示,若sx为0,则宽度为0,不会显示,sy同理
(0,1) 根据缩放中心缩小到n
1 不变
(1,+∞) 根据缩放中心放大n倍

缩放的中心默认为坐标原点,而缩放中心轴就是坐标轴。

旋转(rotate)

旋转同样提供了两种方法:

1
2
public void rotate (float degrees)
public final void rotate (float degrees, float px, float py)

和缩放一样。第二种方法的后两个参数也是用来控制旋转中心点的,默认的旋转中心点依旧是左边原点。

感觉它很鸡肋?试试这段代码。

1
2
3
4
5
6
7
8
9
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawCircle(0, 0, 200, mPaint);
canvas.drawCircle(0, 0, 220, mPaint);
for (int i = 0; i < 36; i++) {
canvas.drawLine(0, 200, 0, 220, mPaint);
canvas.rotate(10);
}

错切(skew)

错切是特殊类型的线性变换,它只提供了一种方法:

1
public void skew (float sx, float sy)

参数含义:

  • sx:将画布在X轴方向上倾斜相应的角度,sx为倾斜角度的tan值。
  • sy:将画布在Y轴方向上倾斜相应的角度,sy为倾斜角度的tan值。

变换后:

​ X = x + sx * y

​ Y = sy * x + y

快照(save)和回滚(restore)

画布的操作是不可逆的,而且很多画布操作会影响后续的操作,所以会对画布的一些状态进行保存和回滚。

与之相关的API:

相关API 说明
save 把当前的画布的状态进行保存,然后放入特定的栈中
saveLayerXxx 新建一个图层,并放入特定的栈中
restore 把栈中最顶层的画布状态取出来,并按照这个状态恢复当前的画布
restoreToCount 弹出指定位置及其以上所有的状态,并按照指定位置的状态进行恢复
getSaveCount 获取栈中内容的数量(即保存次数)

这里的栈可以类比Activity任务栈。

这个东西我感觉是很少用到,待用到的时候再说吧,简单了解一下就OK了。

我们一直都向往,面朝大海,春暖花开。 但是几人能做到,心中有爱,四季不败?