一、前言
本文主要是对《Android 自定义控件高级进阶与精彩实例》一书的理解。
二、set、pre、post
这三个单词是Matrix
中函数的前缀。比如:
setRotate(float degree)
preRotate(float degree)
postRotate(float degree)
这三个函数的区别是什么呢?在这里首先要知道Matrix
的含义,“矩阵”。这是一个源于线性代数的一个概念(这里就不具体讲述线性代数的概念,只是大概的叙述下)。大致表示形式如下
{ 1 2 3 4 5 6 7 8 9 } \left\{ \begin{matrix} 1 & 2 & 3\\ 4 & 5 & 6\\ 7 & 8 & 9\\ \end{matrix} \right\} ⎩⎨⎧147258369⎭⎬⎫
矩阵有各种计算方式,其中有两个计算方式为前乘
(右乘
)、后乘
(左乘
)。这我们使用公式简单描述下.
假设我们有一个矩阵M,一个乘数矩阵T,结果矩阵为S。
那么使用前乘
的计算公式如下:
S = M × T S = M \times T S=M×T
使用后乘
的计算公式如下:
S = T × M S = T \times M S=T×M
需要注意的是矩阵之间的乘除与常量的加减乘除不一样,上面两个公式计算出来的结果是不同的。
假设我们有三个矩阵M、T、R分别使用前乘
。那么公式如下
S = M × T × R S = M \times T \times R S=M×T×R
该公式可以转换成以下方式
S = ( M × T ) × R S = ( M \times T) \times R S=(M×T)×R
这里我们在假设我们有三个矩阵M、T、R分别使用后乘
。那么它们的计算规则为先计算M与T,得出结果M1,再将该结果与R进行计算
M 1 = T × M M1 = T \times M M1=T×M
S = R × M 1 S = R \times M1 S=R×M1
将上述两个公式进行合并即可知道为以下公式
S = R × T × M S = R \times T \times M S=R×T×M
所以倘若M与T进行前乘,与R进行后乘。那么其结果如下
S = R × ( M × T ) S = R \times ( M \times T ) S=R×(M×T)
在代码中pre
代表了前乘
,post
代表了后乘
(set
操作会清空矩阵设置为当前值,但是该结果没有验证)。
三、还原坐标系原点
在使用矩阵的时候通常会对其坐标系原点进行更改,但是更改完后需要还原,否则会影响后面操作。通常可以使用以下方式:
Matrix matrix = new Matrix();
//各种操作
...
matrix.preTranslate(-centerX,-centerY);
matrix.postTranslate(centerX,centerY);
基于上述公式的理解,可以知道在操作完毕后为什么这两句代码可以重置坐标系原点了。这里再次进行分析如下:
假设我们需要围绕中心原点进行旋转。所以需要以下几步:
- 移动坐标系原点到中心 => M1
- 旋转 => M2
- 还原坐标系原点 => M3
每一步分别得到的结果矩阵为 M1、M2、M3。那么其计算公式如下
S = M 1 × M 2 × M 3 S = M1 \times M2 \times M3 S=M1×M2×M3
从公式可以知道三个函数都使用前乘的函数即可
Matrix matrix = new Matrix();
matrix.preTranslate(centerX,centerY);
matrix.preRotate(degree);
matrix.preTranslate(-centerX,-centerY);
同理也可以使用后乘将公式进行转换
Matrix matrix = new Matrix();
matrix.preRotate(degree);
matrix.preTranslate(-centerX,-centerY);
matrix.postTranslate(centerX,centerY);
其公式如下
S 1 = M 2 × M 3 S1 = M2 \times M3 S1=M2×M3
S = M 1 × S 1 S = M1 \times S1 S=M1×S1
将上述两个公式进行合并即可知道为以下公式
S = M 1 × ( M 2 × M 3 ) S = M1 \times ( M2 \times M3 ) S=M1×(M2×M3)
移除小括号为
S = M 1 × M 2 × M 3 S = M1 \times M2 \times M3 S=M1×M2×M3
可知两种写法一样。只是后者更好维护一点