★60.自定義控件 ★15.Matrix詳解

構造方法

Matrix ()
Matrix (Matrix src)

基本方法

  1. equals():比較兩個Matrix的數(shù)值是否相同。
  2. hashCode():獲取Matrix的哈希值唇辨。
  3. toString():將Matrix轉換為字符串: Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}放妈。
  4. toShortString():將Matrix轉換為短字符串: [1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]倔撞。

數(shù)值操作

set

沒有返回值盒犹,有一個參數(shù)权悟,作用是將參數(shù)Matrix的數(shù)值復制到當前Matrix中缰揪。如果參數(shù)為空陨享,則重置當前Matrix,相當于reset()钝腺。

void set (Matrix src)

reset

重置當前Matrix(將當前Matrix重置為單位矩陣)抛姑。

void reset ()

setValues

setValues()的參數(shù)是浮點型的一維數(shù)組,長度需要大于9艳狐,拷貝數(shù)組中的前9位數(shù)值賦值給當前Matrix定硝。

void setValues(float[] values)

getValues

參數(shù)是浮點型的一維數(shù)組,長度需要大于9毫目,將Matrix中的數(shù)值拷貝進參數(shù)的前9位中蔬啡。

void getValues(float[] values)

數(shù)值計算

mapPoints

計算一組點基于當前Matrix變換后的位置,(由于是計算點镀虐,所以參數(shù)中的float數(shù)組長度一般都是偶數(shù)的,若為奇數(shù)箱蟆,則最后一個數(shù)值不參與計算)。

void mapPoints(float[] pts)
void mapPoints(float[] dst, float[] src)
void mapPoints(float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount)

方法一

void mapPoints (float[] pts) 方法僅有一個參數(shù)刮便,pts數(shù)組作為參數(shù)傳遞原始數(shù)值空猜,計算結果仍存放在pts中。

方法二

void mapPoints (float[] dst, float[] src)src作為參數(shù)傳遞原始數(shù)值辈毯,計算結果存放在dst中久信,src不變。

方法三

void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) 可以指定只計算一部分數(shù)值漓摩。

參數(shù) 摘要
dst 目標數(shù)據(jù)
dstIndex 目標數(shù)據(jù)存儲位置起始下標
src 源數(shù)據(jù)
srcIndex 源數(shù)據(jù)存儲位置起始下標
pointCount 計算的點個數(shù)

mapRadius

測量半徑裙士,由于圓可能會因為畫布變換變成橢圓,所以此處測量的是平均半徑管毙。

方法

float mapRadius(float radius)

示例

float radius = 100;
float result = 0;

// 構造一個matrix腿椎,x坐標縮放0.5
Matrix matrix = new Matrix();
matrix.setScale(0.5f, 1f);
Log.i(TAG, "mapRadius: "+radius);
result = matrix.mapRadius(radius);
Log.i(TAG, "mapRadius: "+result);
mapRadius: 100.0
mapRadius: 70.71068

mapRect

測量矩形變換后位置,返回值是判斷矩形經(jīng)過變換后是否仍為矩形夭咬,非90度倍數(shù)的旋轉也會變成非矩形啃炸。

boolean mapRect(RectF rect)
boolean mapRect(RectF dst, RectF src)

方法一

boolean mapRect (RectF rect) 測量rect并將測量結果放入rect中。

方法二

boolean mapRect (RectF dst, RectF src) 測量src并將測量結果放入dst中卓舵。

mapVectors

測量向量南用,mapVectorsmapPoints 基本上是相同的,可以直接參照上面的mapPoints使用方法掏湾。兩者唯一的區(qū)別就是mapVectors不會受到位移的影響裹虫,這符合向量的定律。

void mapVectors(float[] vecs)
void mapVectors(float[] dst, float[] src)
void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)

set融击、pre 與 post

方法 簡介
set 設置筑公,會覆蓋掉之前的數(shù)值,導致之前的操作失效尊浪。
pre 前乘匣屡,構造矩陣乘式時,往前端壓入乘式因子拇涤。
post 后乘捣作,構造矩陣乘式時,往后端壓入乘式因子鹅士。

特殊方法

setPolyToPoly

簡介

Poly 全稱是 Polygon 券躁,多邊形的意思。setPolyToPoly()最多可以支持4個點如绸。

boolean setPolyToPoly (
        float[] src,    // 原始數(shù)組 src [x,y]嘱朽,存儲內(nèi)容為一組點
        int srcIndex,   // 原始數(shù)組開始位置
        float[] dst,    // 目標數(shù)組 dst [x,y],存儲內(nèi)容為一組點
        int dstIndex,   // 目標數(shù)組開始位置
        int pointCount) // 測控點的數(shù)量 取值范圍是: 0到4
pointCount 摘要
0 相當于reset
1 可以進行 平移
2 可以進行 縮放怔接、旋轉、平移 變換
3 可以進行 縮放稀轨、旋轉扼脐、平移、錯切 變換
4 可以進行 縮放、旋轉瓦侮、平移艰赞、錯切以及任何形變

示例

public class MatrixSetPolyToPolyTest extends View {

    private Bitmap mBitmap;             // 要繪制的圖片
    private Matrix mPolyMatrix;         // 測試setPolyToPoly用的Matrix

    public MatrixSetPolyToPolyTest(Context context) {
        super(context);

        initBitmapAndMatrix();
    }

    private void initBitmapAndMatrix() {
        mBitmap = BitmapFactory.decodeResource(getResources(),
                R.drawable.poly_test);

        mPolyMatrix = new Matrix();


        float[] src = {0, 0,                                    // 左上
                mBitmap.getWidth(), 0,                          // 右上
                mBitmap.getWidth(), mBitmap.getHeight(),        // 右下
                0, mBitmap.getHeight()};                        // 左下

        float[] dst = {0, 0,                                    // 左上
                mBitmap.getWidth(), 400,                        // 右上
                mBitmap.getWidth(), mBitmap.getHeight() - 200,  // 右下
                0, mBitmap.getHeight()};                        // 左下

        // 核心要點
        mPolyMatrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); // src.length >> 1 為位移運算 相當于處以2

        // 此處為了更好的顯示對圖片進行了等比縮放和平移(圖片本身有點大)
        mPolyMatrix.postScale(0.26f, 0.26f);
        mPolyMatrix.postTranslate(0,200);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 根據(jù)Matrix繪制一個變換后的圖片
        canvas.drawBitmap(mBitmap, mPolyMatrix, null);
    }
}

pointCount為0

pointCount()0reset()是等價的。

pointCount為1

pointCount()1translate是等價的肚吏,平移的距離是dst - src方妖。

pointCount為2

pointCount2的時候,可以做縮放罚攀、平移和旋轉党觅。

pointCount為3

pointCount3的時候,可以做縮放斋泄、平移杯瞻、旋轉和錯切。

pointCount為4

pointCount4的時候炫掐,你可以將圖像拉伸為任意四邊形魁莉。

setRectToRect

簡介

將源矩形的內(nèi)容填充到目標矩形中。

boolean setRectToRect (RectF src,           // 源區(qū)域
                RectF dst,                  // 目標區(qū)域
                Matrix.ScaleToFit stf)      // 縮放適配模式

Matrix.ScaleToFit

模式 摘要
CENTER 居中募胃,對src等比例縮放旗唁,將其居中放置在dst中。
START 頂部痹束,對src等比例縮放逆皮,將其放置在dst的左上角。
END 底部参袱,對src等比例縮放电谣,將其放置在dst的右下角。
FILL 充滿抹蚀,拉伸src的寬和高剿牺,使其完全填充滿dst。

圖示

src(原始狀態(tài))
CENTER
START
END
FILL

示例

展示居中例子:

public class MatrixSetRectToRectTest extends View {
    private static final String TAG = "MatrixSetRectToRectTest";

    private int mViewWidth, mViewHeight;

    private Bitmap mBitmap;             // 要繪制的圖片
    private Matrix mRectMatrix;         // 測試etRectToRect用的Matrix

    public MatrixSetRectToRectTest(Context context) {
        super(context);

        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.rect_test);
        mRectMatrix = new Matrix();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mViewWidth = w;
        mViewHeight = h;

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        RectF src= new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight() );
        RectF dst = new RectF(0, 0, mViewWidth, mViewHeight );

        // 核心要點
        mRectMatrix.setRectToRect(src,dst, Matrix.ScaleToFit.CENTER);

        // 根據(jù)Matrix繪制一個變換后的圖片
        canvas.drawBitmap(mBitmap, mRectMatrix, new Paint());
    }
}

rectStaysRect

判斷矩形經(jīng)過變換后是否仍為矩形环壤,假如Matrix進行了平移晒来、縮放則畫布僅僅是位置和大小改變,矩形變換后仍然為矩形郑现,但Matrix進行了非90度倍數(shù)的旋轉或者錯切湃崩,則矩形變換后就不再是矩形了。

setSinCos

簡介

設置sinCos值接箫,這個是控制Matrix旋轉的攒读,由于Matrix已經(jīng)封裝好了Rotate方法,所以這個并不常用辛友。

// 方法一
void setSinCos (float sinValue,     // 旋轉角度的sin值
                float cosValue)     // 旋轉角度的cos值

// 方法二
void setSinCos (float sinValue,     // 旋轉角度的sin值
                float cosValue,     // 旋轉角度的cos值
                float px,           // 中心位置x坐標
                float py)           // 中心位置y坐標

示例

Matrix matrix = new Matrix();
// 旋轉90度
// sin90=1
// cos90=0
matrix.setSinCos(1f, 0f);
Log.i(TAG, "setSinCos:"+matrix.toShortString());
// 重置
matrix.reset();
// 旋轉90度
matrix.setRotate(90);
Log.i(TAG, "setRotate:"+matrix.toShortString());
setSinCos:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0]
setRotate:[0.0, -1.0, 0.0][1.0, 0.0, 0.0][0.0, 0.0, 1.0]

矩陣相關

方法 摘要
invert 求矩陣的逆矩陣
isAffine 判斷當前矩陣是否為仿射矩陣薄扁,API21(5.0)才添加的方法剪返。
isIdentity 判斷當前矩陣是否為單位矩陣。

invert

求矩陣的逆矩陣邓梅,簡而言之就是計算與之前相反的矩陣脱盲,如果之前是平移200px,則求的矩陣為反向平移200px日缨,如果之前是縮小到0.5f钱反,則結果是放大到2倍。

boolean invert(Matrix inverse)

isAffine

判斷是否是仿射矩陣最重要的一點就是匣距,直線是否仍為直線面哥,簡單想一下就知道,不論平移墨礁,旋轉幢竹,錯切,縮放恩静,直線變換后最終仍為直線焕毫,要想讓isAffine()的結果變?yōu)?code>false,除非你能把直線掰彎驶乾。

boolean isAffine()

isIdentity

判斷是否為單位矩陣邑飒。

實用技巧

獲取View在屏幕上的絕對位置。

@Override
protected void onDraw(Canvas canvas) {
    // 方式一:
    float[] values = new float[9];
    int[] location1 = new int[2];
    Matrix matrix = canvas.getMatrix();
    matrix.getValues(values);
    location1[0] = (int) values[2];
    location1[1] = (int) values[5];
    Log.i(TAG, "location1 = " + Arrays.toString(location1));

    // 方式二:
    int[] location2 = new int[2];
    this.getLocationOnScreen(location2);
    Log.i(TAG, "location2 = " + Arrays.toString(location2));
}
location1 = [0, 243]
location2 = [0, 243]

利用setPolyToPoly制造3D效果

Android FoldingLayout 折疊布局 原理及實現(xiàn)(一)
Android FoldingLayout 折疊布局 原理及實現(xiàn)(二)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末级乐,一起剝皮案震驚了整個濱河市疙咸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌风科,老刑警劉巖撒轮,帶你破解...
    沈念sama閱讀 216,744評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贼穆,居然都是意外死亡题山,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評論 3 392
  • 文/潘曉璐 我一進店門故痊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顶瞳,“玉大人,你說我怎么就攤上這事愕秫】猓” “怎么了?”我有些...
    開封第一講書人閱讀 163,105評論 0 353
  • 文/不壞的土叔 我叫張陵戴甩,是天一觀的道長符喝。 經(jīng)常有香客問我,道長等恐,這世上最難降的妖魔是什么洲劣? 我笑而不...
    開封第一講書人閱讀 58,242評論 1 292
  • 正文 為了忘掉前任备蚓,我火速辦了婚禮课蔬,結果婚禮上囱稽,老公的妹妹穿的比我還像新娘。我一直安慰自己二跋,他們只是感情好战惊,可當我...
    茶點故事閱讀 67,269評論 6 389
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著扎即,像睡著了一般吞获。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谚鄙,一...
    開封第一講書人閱讀 51,215評論 1 299
  • 那天各拷,我揣著相機與錄音,去河邊找鬼闷营。 笑死烤黍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的傻盟。 我是一名探鬼主播速蕊,決...
    沈念sama閱讀 40,096評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼娘赴!你這毒婦竟也來了规哲?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,939評論 0 274
  • 序言:老撾萬榮一對情侶失蹤诽表,失蹤者是張志新(化名)和其女友劉穎唉锌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體竿奏,經(jīng)...
    沈念sama閱讀 45,354評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡袄简,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,573評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了议双。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痘番。...
    茶點故事閱讀 39,745評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖平痰,靈堂內(nèi)的尸體忽然破棺而出汞舱,到底是詐尸還是另有隱情,我是刑警寧澤宗雇,帶...
    沈念sama閱讀 35,448評論 5 344
  • 正文 年R本政府宣布昂芜,位于F島的核電站,受9級特大地震影響赔蒲,放射性物質(zhì)發(fā)生泄漏泌神。R本人自食惡果不足惜良漱,卻給世界環(huán)境...
    茶點故事閱讀 41,048評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望欢际。 院中可真熱鬧母市,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蒋失,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桐玻,已是汗流浹背篙挽。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镊靴,地道東北人铣卡。 一個月前我還...
    沈念sama閱讀 47,776評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像邑闲,于是被迫代替她去往敵國和親算行。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,652評論 2 354

推薦閱讀更多精彩內(nèi)容