Matrix — är en klass från Android SDK (android.graphics.Matrix) som representerar en affin transformation genom en 3×3-matris. Den används för transformation av grafiska objekt — flyttning, skalning, rotation och lutning. Enligt Android Developers Documentation (2026) är Matrix det främsta verktyget för att arbeta med transformationer i Canvas, Bitmap och Drawable, och ger exakt koordinatkontroll vid anpassad ritning.
Huvudpunkter
Matrix (android.graphics.Matrix) — är en Android SDK-klass som representerar en matematisk 3×3-matris som används för transformation av tvådimensionella koordinater. Matrix är den grundläggande byggstenen för alla grafiska transformationer i Android — från förflyttning och skalning av Canvas till komplexa perspektiviska deformationer av Bitmap.
Till skillnad från iOS, där separata strukturer CGAffineTransform (affina) och CATransform3D (3D) används, kombinerar Android affina och perspektiviska transformationer i en enda klass Matrix. 3×3-matrisen gör det möjligt att representera både standard affina operationer (sista raden [0, 0, 1]) och perspektiviska deformationer när den sista raden innehåller godtyckliga värden. Detta ger större flexibilitet, men kräver förståelse för matrismatematik.
Matrix är nära integrerad med Canvas API. När en utvecklare anropar canvas.translate(), canvas.scale() eller canvas.rotate(), modifierar dessa metoder internt matrisen för det grafiska sammanhanget. Den aktuella matrisen för Canvas kan erhållas via canvas.getMatrix(), och en anpassad matris kan appliceras manuellt via canvas.setMatrix() eller canvas.concat().
Matrix stöder fyra grundläggande typer av affina transformationer: translate, scale, rotate, skew (lutning). Varje typ har metoder för förmultiplikation (pre), eftermultiplikation (post) och inställning (set). Skillnaden mellan preTranslate och postTranslate ligger i ordningen för matrismultiplikation, vilket påverkar den slutliga transformationen vid kombination.
| Operation | Metod | Parametrar | Beskrivning |
|---|---|---|---|
| Translate | setTranslate / preTranslate / postTranslate | dx, dy | Förflyttning längs X- och Y-axeln |
| Scale | setScale / preScale / postScale | sx, sy, px, py | Skalning med referenspunkt |
| Rotate | setRotate / preRotate / postRotate | degrees, px, py | Rotation runt referenspunkt |
| Skew | setSkew / preSkew / postSkew | kx, ky | Lutning (skjuvning) längs axlar |
Translate ändrar positionen för alla punkter med den givna förskjutningen dx, dy. Positivt dx flyttar åt höger, dy — nedåt (i Android-skärmens koordinatsystem är Y-axeln riktad nedåt). Translate ändrar inte objektets form — endast dess position. Detta är den enklaste och mest använda operationen för att positionera element.
Scale ändrar objektets storlek med faktorerna sx (längs X) och sy (längs Y). Parametrarna px, py anger referenspunkten för skalning (pivot point). Om px, py inte anges utförs skalningen relativt origo (0, 0). När sx = sy skaleras objektet enhetligt. Negativa värden skapar en spegling.
Rotate roterar objektet med en given vinkel (i grader) runt referenspunkten (px, py). Positivt gradtal motsvarar rotation medurs (till skillnad från iOS/macOS, där positiv vinkel är moturs). Om px, py inte anges utförs rotationen runt origo.
Skew (skjuvning) deformera objektet genom att luta det längs X-axeln (kx) eller Y-axeln (ky). Värdet 1.0 lutar 45 grader. Skew används för att skapa lutningseffekter, simulera tredimensionell vy (pseudo-3D) och perspektivisk deformation.
Matrix lagrar elementen i 3×3-matrisen i en intern array med 9 flyttalsvärden (float[9]). Lagringsordningen är column-major (per kolumn), vilket motsvarar standard matematisk representation. Åtkomst till enskilda element sker via konstanter: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X och så vidare.
Matrisen är organiserad på följande sätt: de första två kolumnerna (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) ansvarar för skalning, rotation och lutning. Den tredje kolumnen (MTRANS_X, MTRANS_Y, MPERSP_2) — för förflyttning och perspektiv. För affin transformation är MPERSP_0 och MPERSP_1 lika med 0, och MPERSP_2 är lika med 1.
För att hämta matrisvärden används getValues(float[] values), som fyller en array med 9 element. För inställning — setValues(float[] values). Detta möjliggör direkt manipulation av matrisen för komplexa anpassade transformationer som går utöver standardmetoderna translate, scale, rotate och skew.
Matrix tillhandahåller flera metoder för klassificering av aktuellt tillstånd. isIdentity() kontrollerar om matrisen är enhetsmatris. isAffine() — om den endast innehåller affina transformationer (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Dessa kontroller är användbara för optimering: om matrisen är enhetsmatris kan transformationen hoppas över.
Matrix stöder flera kategorier av operationer: inställning (set), förmultiplikation (pre), eftermultiplikation (post), konkatenering (concat), invertering (invert) och mappning (map). Varje kategori löser sin uppgift vid konstruktion av komplexa transformationer.
preTranslate multiplicerar den aktuella matrisen från vänster med förskjutningsmatrisen: result = translate × current. postTranslate multiplicerar från höger: result = current × translate. Skillnaden ligger i tillämpningsordningen: pre-operationer tillämpas före aktuella transformationer, post-operationer — efter. preScale, postScale, preRotate, postRotate och preSkew, postSkew fungerar på samma sätt.
invert(Matrix inverse) beräknar den inversa matrisen. Om källmatrisen är degenererad (determinanten är noll), returneras false. concat(Matrix other) multiplicerar den aktuella matrisen med den givna matrisen: set = set × other. För omvänd ordning, använd setConcat(other, this).
mapRect(RectF rect) transformerar rektangeln och returnerar resultatet i en ny RectF. mapPoints(float[] dst, float[] src) transformerar en array av punkter. mapVectors(float[] dst, float[] src) transformerar vektorer — utan hänsyn till förflyttning (translate). mapRect är användbart för att beräkna bounding box efter transformation.
Matrix används aktivt i två viktiga scenarier inom Android-grafik: Canvas-transformation och Bitmap-transformation. I båda fallen avgör Matrix hur den grafiska utskriften ändras.
Canvas tillhandahåller metoderna canvas.setMatrix(matrix) för fullständig ersättning av den aktuella matrisen och canvas.concat(matrix) för multiplikation av den aktuella transformationen med den givna. Efter tillämpning av Matrix utförs all efterföljande ritning — anrop till drawBitmap, drawRect, drawPath — i det transformerade koordinatsystemet. Canvas behåller också sin egen stack av sparade tillstånd genom save() och restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) skapar en ny Bitmap med tillämpning av den givna transformationen. Detta är ett kraftfullt verktyg för att skapa skalade, roterade eller deformerade kopior av bilder utan att förlora den ursprungliga Bitmap. Parametern filter styr utjämning vid pixelinterpolation.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — en unik förmåga hos Matrix, utan direkt motsvarighet i CGAffineTransform. Den beräknar en matris som transformerar givna punkter från en polygon till en annan. Vid pointCount = 4 skapas en fullständig perspektivisk (projektiv) transformation, vilket möjliggör applicering av Bitmap med perspektivisk deformation.
Låt oss titta på praktiska exempel på användning av Matrix för grafisk transformation i en Android-applikation i Kotlin.
Exemplet skapar en Matrix för en kombinerad transformation: förflyttning med (100, 50), 1.5 gångers skalning och rotation på 45 grader. Användning av postTranslate efter preRotate och preScale ändrar ordningen för tillämpning av operationer.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Tillämpa på punkter
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Tillämpa på rektangel
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
Exemplet demonstrerar tillämpning av Matrix på Canvas i onDraw för rotation och skalning av en cirkel runt dess centrum. Sparande och återställande av Canvas-tillståndet garanterar att transformationen inte påverkar efterföljande ritelement.
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = 100f
canvas.save()
val matrix = Matrix()
matrix.postTranslate(cx, cy)
matrix.postRotate(30f)
matrix.postScale(1.2f, 1.2f)
canvas.concat(matrix)
val paint = Paint().apply {
color = Color.BLUE
style = Paint.Style.FILL
}
canvas.drawCircle(0f, 0f, radius, paint)
canvas.restore()
}
Exemplet använder setPolyToPoly för att skapa perspektivisk deformation av Bitmap. Fyra källpunkter (hörnen på den ursprungliga rektangeln) mappas till fyra målpunkter som bildar en trapets. Resultatet — en effekt av en bild som lutar i rymden.
fun applyPerspective(
bitmap: Bitmap,
skew: Float
): Bitmap {
val w = bitmap.width.toFloat()
val h = bitmap.height.toFloat()
val src = floatArrayOf(0f, 0f, w, 0f,
0f, h, w, h)
val dst = floatArrayOf(skew, 0f, w - skew, 0f,
0f, h, w, h)
val matrix = Matrix()
matrix.setPolyToPoly(src, 0, dst, 0, 4)
return Bitmap.createBitmap(
bitmap, 0, 0,
w.toInt(), h.toInt(),
matrix, true
)
}
Vanliga frågor
Matrix arbetar med tvådimensionella affina och perspektiviska transformationer genom en 3×3-matris. Camera (android.graphics.Camera) — är en klass på högre nivå som simulerar en tredimensionell kamera: den skapar 3D-rotation och projicerar sedan resultatet till 2D Matrix. Camera använder Matrix internt.
Skapa en Matrix med postRotate(90f) och skicka den till Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Observera att vid rotation på 90 grader byter resultatets bredd och höjd plats. För rotation i godtycklig vinkel kan beskärning krävas för att undvika tomma områden.
Använd matrix.invert(resultMatrix). Metoden returnerar true om inverteringen är framgångsrik och skriver den inversa matrisen till resultMatrix. Invertering kan vara omöjlig om matrisen är degenererad (till exempel vid noll skalning). Kontrollera alltid returvärdet.
pre multiplicerar den nya transformationen från vänster: result = operation × current — operationen tillämpas före aktuella transformationer. post multiplicerar från höger: result = current × operation — operationen tillämpas efter aktuella transformationer. För sekvensen preRotate + postTranslate: först rotation, sedan förflyttning.
Ja, Matrix används i Jetpack Compose via klassen android.graphics.Matrix i interaktion med Canvas Compose. I Compose är graphicsLayer tillgängligt för transformation (scale, rotationX, translationX och andra), men för komplexa Bitmap-transformationer tillämpas Matrix i koden drawWithContent eller drawBehind.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också