Matrix就是矩陣的意思,所有的控件中都有Matrix的身影。
Matrix是一個(gè)三階矩陣,主要功能是坐標(biāo)映射,數(shù)值變換,見(jiàn)下圖

再講下邊的內(nèi)容之間,先提前介紹一下下邊用到的名詞:
| 名詞 | 解釋 |
|---|---|
| 單位矩陣 | ![]() 單位矩陣
|
| M | 原始矩陣,沒(méi)有變換之前的矩陣 |
| A | 變換 |
| M` | 結(jié)果矩陣 |
| T | 平移變換 |
| -T | 反向平移變換 |
| R | 旋轉(zhuǎn)變換 |
Matrix基本原理
Matrix的根本作用就是坐標(biāo)的變化;基本變換有平移(translate),縮放(scale),旋轉(zhuǎn)(skew),錯(cuò)切四種。


最后一行的數(shù)據(jù)透視使用在3D變換中
縮放(scale)
在進(jìn)行縮放的時(shí)候需要變換(MSCALE_X,MSCALE_Y)這兩個(gè)值,分別作用于x和y。

X=K1*X0
Y=K2*Y0
錯(cuò)切(skew)
錯(cuò)切需要變換(MSKEW_X,MSKEW_Y),分別作用于水平錯(cuò)切和垂直錯(cuò)切;

X=X0+K1*Y0
Y=K2*X0+Y0
旋轉(zhuǎn)(rotate)
當(dāng)要旋轉(zhuǎn) θ角度的時(shí)候,博客中計(jì)算了一遍,講了下邊矩陣變換數(shù)據(jù)的來(lái)歷,我看了一遍也記不住,還是及這個(gè)圖來(lái)的快。。。。

平移(translate)
平移需要修改的是最后一列的前兩個(gè)數(shù)據(jù)(MTRANS_X,MTRANS_Y),分別作用在x和y 上。

總結(jié)
看了上邊的幾種變換,其實(shí)就是對(duì)應(yīng)修改單位矩陣中的特定數(shù)值。比如說(shuō),要旋轉(zhuǎn),就要修改左上角四個(gè)數(shù)值,得到變換矩陣,拿變換矩陣跟原始矩陣相乘。平移,就是修改單位矩陣中最后一列的上邊兩個(gè)數(shù)值,如果你只想在x軸平移,那么只需要修改最后一列的第一個(gè)數(shù)據(jù)??戳松线叺臇|西,大概知道矩陣作用了,可是矩陣該怎么在實(shí)際代碼中使用呢?一步一步來(lái)
Matrix 矩陣復(fù)合原理
矩陣復(fù)合有三種,前乘(pre),后乘(post),設(shè)置(set)
為什么會(huì)有前乘和后乘的區(qū)別呢?
因?yàn)?/p>
矩陣乘法不滿足交換律,即 AB ≠ BA
矩陣乘法滿足結(jié)合律,即 (AB)C = A(BC)
矩陣與單位矩陣相乘結(jié)果不變,即 A * I = A
前乘(pre)
前乘就是原始矩陣在前邊,變換矩陣在后邊
M`=M*A
后乘(post)
后乘就是原始矩陣在后邊,變換矩陣在前邊
M`=S*A
設(shè)置(set)
設(shè)置不是矩陣的乘法,而是覆蓋原來(lái)的矩陣,使用設(shè)置之后會(huì)對(duì)之前的操作有影響。
幾個(gè)常見(jiàn)的錯(cuò)誤結(jié)論:
1.pre 是順序執(zhí)行,post 是逆序執(zhí)行
2.pre 是先執(zhí)行,而 post 是后執(zhí)行
其實(shí)前乘后乘執(zhí)行的順序,跟這句代碼所在的位置沒(méi)有關(guān)系。
下邊將一個(gè)遠(yuǎn)博客中的例子。
我們想講一個(gè)控件先平移到屏幕的中間,然后對(duì)控件做一系列縮放,錯(cuò)切,平移等等操作,最后我們?cè)賹⒖丶揭苹剡h(yuǎn)位置。
上面的操作我們可以使用三種方法實(shí)現(xiàn):
第一種前后兩個(gè)平移全部使用前乘(pre)
Matrix matrix=new Matrix();
matrix.preTranslate(200,200);
matrix.preRotate(angle);
matrix.preTranslate(-200,-200);
M`=M*T*R-T
新實(shí)例化的矩陣就是單位矩陣,所以這里M為原始矩陣,所以上邊的式子可以簡(jiǎn)化為
M`=*T*R-T
第二種前后兩個(gè)平移全部使用后乘
Matrix matrix=new Matrix();
matrix.postTranslate(-200,-200);
matrix.postRotate(angle);
matrix.postTranslate(-200,-200);
化簡(jiǎn)公式為M`=T*R*-T*
混合使用前乘和后乘
Matrix matrix = new Matrix();
// 各種操作,旋轉(zhuǎn),縮放,錯(cuò)切等,可以執(zhí)行多次。
matrix.postTranslate(pivotX,pivotY);
matrix.preTranslate(-pivotX, -pivotY);
M' = TM ... -T = T ... *-T
這種方法是為了避免兩次平移被拉得太開(kāi),代碼量多的話,會(huì)容易漏寫(xiě)。
pre 和 post 就是用來(lái)調(diào)整乘法順序的,由于矩陣乘法不滿足交換律,所以前乘后乘的結(jié)果是不一樣的。
上面都是矩陣的基礎(chǔ)知識(shí)的理解,到底該怎么用。下邊開(kāi)始總結(jié):
Matrix的基本使用
先看一下Matrix的基礎(chǔ)方法
| 方法 | 解釋 |
|---|---|
| Matrix (); | 構(gòu)造方法,創(chuàng)建一個(gè)新的矩陣,為單位矩陣 |
| Matrix (Matrix src); | 構(gòu)造方法,對(duì)src矩陣進(jìn)行深拷貝,也就是創(chuàng)建一個(gè)跟src矩陣一毛一樣的矩陣。 |
| equals | 比較兩個(gè)Matrix的數(shù)值是否相同。 |
| hashCode | 獲取Matrix的哈希值。 |
| toString | 將Matrix轉(zhuǎn)換為字符串: Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} |
| toShortString | 將Matrix轉(zhuǎn)換為短字符串: [1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0] |
| void set (Matrix src) | 沒(méi)有返回值,有一個(gè)參數(shù),作用是將參數(shù)Matrix的數(shù)值復(fù)制到當(dāng)前Matrix中。如果參數(shù)為空,則重置當(dāng)前Matrix,相當(dāng)于reset()。 |
| void reset () | 重置當(dāng)前Matrix(將當(dāng)前Matrix重置為單位矩陣)。 |
| void setValues (float[] values) | setValues的參數(shù)是浮點(diǎn)型的一維數(shù)組,長(zhǎng)度需要大于9,拷貝數(shù)組中的前9位數(shù)值賦值給當(dāng)前Matrix。 |
| void getValues (float[] values) | 很顯然,getValues和setValues是一對(duì)方法,參數(shù)也是浮點(diǎn)型的一維數(shù)組,長(zhǎng)度需要大于9,將Matrix中的數(shù)值拷貝進(jìn)參數(shù)的前9位中。 |
數(shù)值計(jì)算方法
| 方法 | 解釋 |
|---|---|
| void mapPoints (float[] pts) | 計(jì)算一組點(diǎn)基于當(dāng)前Matrix變換后的位置,講計(jì)算后的矩陣數(shù)值存放到pts數(shù)組中 |
| void mapPoints (float[] dst, float[] src) | 與上個(gè)方法作用一樣,只不過(guò)是講計(jì)算后的結(jié)果存放到dst數(shù)組中,src不變 |
| void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) | 作用和上邊兩個(gè)方法一致,只不過(guò)可以指定存儲(chǔ)的數(shù)組長(zhǎng)度。dstIndex表示目標(biāo)數(shù)據(jù)存儲(chǔ)位置起始下標(biāo),srcIndex表示原數(shù)據(jù)存儲(chǔ)起始下標(biāo),pointCount表示計(jì)算的點(diǎn)個(gè)數(shù) |
| float mapRadius (float radius) | 測(cè)量半徑,由于圓可能會(huì)因?yàn)楫?huà)布變換變成橢圓,所以此處測(cè)量的是平均半徑。radius表示原半徑,返回的是經(jīng)過(guò)變換之后的半徑。 |
| boolean mapRect (RectF rect) | 測(cè)量rect并將測(cè)量結(jié)果放入rect中,返回值是判斷矩形經(jīng)過(guò)變換后是否仍為矩形 |
| boolean mapRect (RectF dst, RectF src) | 測(cè)量src并將測(cè)量結(jié)果放入dst中,返回值是判斷矩形經(jīng)過(guò)變換后是否仍為矩形 |
| mapVectors | 和上邊mapPoints方法類似,不過(guò)這里測(cè)量的是向量,也就是說(shuō)平移操作不會(huì)影響結(jié)果 |
set/pre/post控制平移(translate)、縮放(scale)、旋轉(zhuǎn)(rotate)、 錯(cuò)切(skew) 的變換
上邊在講Matrix原理的時(shí)候就已經(jīng)對(duì)這些方法進(jìn)行過(guò)講解。
特殊方法
setPoluToPoly()
boolean setPolyToPoly (
float[] src, // 原始數(shù)組 src [x,y],存儲(chǔ)內(nèi)容為一組點(diǎn)
int srcIndex, // 原始數(shù)組開(kāi)始位置
float[] dst, // 目標(biāo)數(shù)組 dst [x,y],存儲(chǔ)內(nèi)容為一組點(diǎn)
int dstIndex, // 目標(biāo)數(shù)組開(kāi)始位置
int pointCount) // 測(cè)控點(diǎn)的數(shù)量 取值范圍是: 0到4
這個(gè)方法是控制兩部分進(jìn)行變換的。一是進(jìn)行變換的點(diǎn)的數(shù)據(jù),而是變化的點(diǎn)數(shù)。
srcIndex定義要變換哪些點(diǎn),中心點(diǎn)可以,四邊形四邊中點(diǎn)可以,四邊形四個(gè)角可以,這里去的是容易獲取的點(diǎn);dstIndex表示根據(jù)srcIndex變換后的點(diǎn);pointCount是變換點(diǎn)的數(shù)量;比如說(shuō)你上邊定義了四個(gè)點(diǎn)的變化,但是pointCount是1,那么結(jié)果可能就不是你想要得到的。
| pointCount | 摘要 |
|---|---|
| 0 | 相當(dāng)于reset |
| 1 | 相當(dāng)于translate |
| 2 | 可以進(jìn)行 縮放、旋轉(zhuǎn)、平移 變換 |
| 3 | 可以進(jìn)行 縮放、旋轉(zhuǎn)、平移、錯(cuò)切 變換 |
| 4 | 可以進(jìn)行 縮放、旋轉(zhuǎn)、平移、錯(cuò)切以及任何形變 |
這個(gè)方法還是很有必要仔細(xì)研究的,具體代碼我就不貼了,原博客中有詳細(xì)講解
setRectToRect
這個(gè)方法的作用主要就是填充的模式,比如一張圖片要放到父空間中,圖片尺寸比較小,那這張圖片是要放在左上角,還是右下角,還是中間,還是鋪滿呢?setRectToRect方法就是控制這些操作的。
boolean setRectToRect (RectF src, // 源區(qū)域
RectF dst, // 目標(biāo)區(qū)域
Matrix.ScaleToFit stf) // 縮放適配模式
| 模式 | 摘要 |
|---|---|
| CENTER | 居中,對(duì)src等比例縮放,將其居中放置在dst中。 |
| START | 頂部,對(duì)src等比例縮放,將其放置在dst的左上角。 |
| END | 底部,對(duì)src等比例縮放,將其放置在dst的右下角。 |
| FILL | 充滿,拉伸src的寬和高,使其完全填充滿dst。 |
rectStaysRect
判斷舉行變換之后是否還是矩形。
invert
獲取矩陣的逆矩陣
boolean invert (Matrix inverse)
