了解Android Matrix轉(zhuǎn)換

ImageView

原文 了解Android Matrix轉(zhuǎn)換

很多年前,在學(xué)校我學(xué)習(xí)了矩陣。 我記不太清楚了,但我記得的是在想,“但是......你對這些知識做了什么呢?”

快進(jìn)幾年,我開始作為Android開發(fā)人員工作,不得不使用ImageViewscaleType - 如果你看過所有可能的類型,你已經(jīng)注意到其中一個是matrix 。 多年來,我一直避開它,使用其他規(guī)模類型或解決問題。 然而幾周前我正在開發(fā)一種設(shè)計,其中組件的背景圖像應(yīng)該與視圖的左上角對齊,而不執(zhí)行任何縮放,如下所示:

ImageView

所以我繼續(xù)添加了一個ImageView并再次瀏覽了所有scaleType - 希望有一個我錯過的類型,但是在我嘗試使用scaleType="matrix"它們都沒有完全正確,它完全符合我的要求。 但為什么這有效呢? 它實際上做了什么?

所以我看了一下Matrix文檔:

Matrix類包含一個3x3矩陣,用于轉(zhuǎn)換坐標(biāo)

嗯......不是很有幫助。 幸運的是,我并不是唯一一個不懂的人, Arnaud Bos寫了一篇很棒的文章 ,詳細(xì)解釋了背后的數(shù)學(xué)(警告:如果你打算閱讀它 - 可能需要一杯咖啡(或者兩杯)的時間)。 如果你在那篇文章的中途迷路了,我不能責(zé)怪你 - 這很復(fù)雜,但好消息是你不必理解數(shù)學(xué)就能用matrix(雖然它很有幫助。

我們怎樣才能使用Matrix?

正如我之前提到的,我們必須在ImageView上設(shè)置scaleType="matrix" 。 但要真正能夠使用它,我們必須在代碼中設(shè)置imageMatrix

imageView.imageMatrix = Matrix().apply {
    // perform transformations
}

現(xiàn)在我們有了這個 - 我們可以用它做什么? 矩陣支持一系列不同的變換,如translate , scale , rotateskew 。 如果這些聽起來很熟悉,因為它們(大多數(shù))與View,動畫或畫布上的相同。

您會發(fā)現(xiàn),對于每個操作,都有一set , pre版本。 稍后我會談到這一點,但是現(xiàn)在我們只使用set版本。

所以,我們能做些什么?

Translating (移動)

ImageView

設(shè)置translation意味著將圖像移動到其他位置。 您所要做的就是使用Matrix上所需的xy坐標(biāo)調(diào)用setTranslate

val dWidth = imageView.drawable.intrinsicWidth
val dHeight = imageView.drawable.intrinsicHeight

val vWidth = imageView.measuredWidth
val vHeight = imageView.measuredHeight
setTranslate(
    round((vWidth - dWidth) * 0.5f),
    round((vHeight - dHeight) * 0.5f)
)

在這個例子中,我們只是將drawable置于View中心,這導(dǎo)致與在ImageView上設(shè)置scaleType="center"相同的行為。 那么讓我們來看看ImageView如何做到這一點:

mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f),
                         Math.round((vheight - dheight) * 0.5f));

它完全一樣! 所以我們不知道它已經(jīng)使用了矩陣變換。

Scaling (縮放)

ImageView

Scaling(正如您可能已經(jīng)猜到的那樣)定義了圖像的大小。 您可以定義兩個值 - 一個用于x軸,另一個用于y軸。 但是,通過縮放,您還可以設(shè)置軸心點。

樞軸點定義轉(zhuǎn)換將保持不變的點。 默認(rèn)情況下它是0, 0 - 左上角 - 意味著圖像將向右和向下延伸,左上角保持不變 - 就像左邊的上面的gif一樣。

如果要從中心縮放圖像(如右側(cè)的gif),可以將軸設(shè)置為圖像的中心,如下所示:

setScale(0.5f, 0.5f, dWidth / 2f, dHeight / 2f)

這將使圖像縮放到其大小的一半,其中心的樞軸點。 如果你只想從左上角縮放它,你可以省略最后兩個參數(shù),如下所示:

setScale(0.5f, 0.5f)

但是你可以用縮放做更多的事情。 如果提供負(fù)比例值,則基本上可以圍繞軸(或兩個)鏡像圖像。 相當(dāng)漂亮!

ImageView

Rotation (旋轉(zhuǎn))

ImageView

你猜對了! 通過旋轉(zhuǎn),您可以旋轉(zhuǎn)圖像。 在這里,我們提供了我們想要旋轉(zhuǎn)的角度,以及一個類似于比例的可選樞軸點。

  setRotate(45f,dWidth / 2f,dHeight / 2f) 

將圖像圍繞圖像中心旋轉(zhuǎn)45度。 如果將它旋轉(zhuǎn)-45度,它將向左旋轉(zhuǎn)。

Skewing (傾斜)

imageView

傾斜可能是你以前沒有聽說過的轉(zhuǎn)變。 傾斜將沿軸(或兩個)拉伸您的圖像,就像上面的GIF一樣。 我們來看一個例子:

  setSkew(1f,0f,dWidth / 2f,dHeight / 2f) 

這會使圖像在x軸(以及中心點周圍)偏斜1,這是圖像的寬度,導(dǎo)致圖像傾斜45度,就像上面的gif一樣。

應(yīng)用多個轉(zhuǎn)換

我們現(xiàn)在可以translate,scale,rotateskew圖像,但是如果我們想要將它們組合起來呢? 顯而易見的事情可能是連續(xù)調(diào)用多個set方法。 但是,這只會應(yīng)用最后一次轉(zhuǎn)換 - 所有以前的轉(zhuǎn)換都將被覆蓋。 這是因為set方法基本上重置了Matrix

但正如我之前提到的,還有每個轉(zhuǎn)換的post版本。 通過使用這些,我們可以應(yīng)用多個變換,并真正利用matrix的魔力。

但是pre的區(qū)別是什么? 對于第一次轉(zhuǎn)換,使用三種版本中的哪一種沒有區(qū)別,但對于任何未來的轉(zhuǎn)換,它可以產(chǎn)生很大的不同。

假設(shè)我們想要將圖像轉(zhuǎn)換為視圖的中心并將其縮放到一半大小。 這兩個版本將產(chǎn)生預(yù)期的效果:

val drawableLeft = round((vWidth - dWidth) * 0.5f)
val drawableTop = round((vHeight - dHeight) * 0.5f)
// Version 1
setTranslate(drawableLeft, drawableTop)
val (viewCenterX, viewCenterY) = vWidth / 2f to vHeight / 2f
postScale(0.5f, 0.5f, viewCenterX, viewCenterY)
// Version 2
setTranslate(drawableLeft, drawableTop)
val (drawableCenterX, drawableCenterY) = dWidth / 2f to dHeight / 2f
preScale(0.5f, 0.5f, drawableCenterX, drawableCenterY)

請注意,在第一個版本中,我們使用postScale和視圖的中心,而在第二個版本中,我們使用preScaledrawable的中心。

使用postScale ,將在translate后應(yīng)用比例轉(zhuǎn)換。 由于圖像已經(jīng)在視圖中居中,我們必須使用視圖的中心點作為樞軸。

val (viewCenterX, viewCenterY) = vWidth / 2f to vHeight / 2f
postScale(0.5f, 0.5f, viewCenterX, viewCenterY)

所以從頭開始回顧這個例子 - 為什么應(yīng)用scaleType="matrix"只是起作用? 使用默認(rèn)martix,比例將為1,平移,旋轉(zhuǎn)和傾斜將為0,因此圖像將在左上角繪制。 所以它完全符合我的需要!

下次您必須以默認(rèn)scaleType不起作用的方式布局圖像時 - 嘗試使用Matrix!

matrix
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容