Matrix — este o clasă din Android SDK (android.graphics.Matrix) care reprezintă o transformare afină printr-o matrice 3×3. Este utilizată pentru transformarea obiectelor grafice — deplasare, scalare, rotire și înclinare. Conform Android Developers Documentation (2026), Matrix este instrumentul principal pentru lucrul cu transformări în Canvas, Bitmap și Drawable, asigurând controlul precis al coordonatelor la desenarea personalizată.
Principalele puncte
Matrix (android.graphics.Matrix) — este o clasă Android SDK care reprezintă o matrice matematică 3×3 utilizată pentru transformarea coordonatelor bidimensionale. Matrix este elementul de bază pentru toate transformările grafice în Android — de la deplasarea și scalarea Canvas până la distorsiunile complexe de perspectivă ale Bitmap.
Spre deosebire de iOS, unde se utilizează structuri separate CGAffineTransform (afine) și CATransform3D (3D), Android combină transformările afine și prospective într-o singură clasă Matrix. Matricea 3×3 permite reprezentarea atât a operațiilor standard afine (ultimul rând [0, 0, 1]), cât și a distorsiunilor de perspectivă când ultimul rând conține valori arbitrare. Aceasta oferă mai multă flexibilitate, dar necesită înțelegerea matematicii matricelor.
Matrix este strâns integrat cu Canvas API. Când dezvoltatorul apelează canvas.translate(), canvas.scale() sau canvas.rotate(), aceste metode modifică intern matricea contextului grafic. Matricea curentă a Canvas poate fi obținută prin canvas.getMatrix(), iar una personalizată poate fi aplicată manual prin canvas.setMatrix() sau canvas.concat().
Matrix suportă patru tipuri de bază de transformări afine: translate, scale, rotate, skew (înclinare). Fiecare tip are metode pentru pre-înmulțire (pre), post-înmulțire (post) și setare (set). Diferența dintre preTranslate și postTranslate constă în ordinea înmulțirii matricelor, ceea ce afectează transformarea finală la combinare.
| Operație | Metodă | Parametri | Descriere |
|---|---|---|---|
| Translate | setTranslate / preTranslate / postTranslate | dx, dy | Deplasare de-a lungul axelor X și Y |
| Scale | setScale / preScale / postScale | sx, sy, px, py | Scalare cu punct de referință |
| Rotate | setRotate / preRotate / postRotate | degrees, px, py | Rotire în jurul punctului de referință |
| Skew | setSkew / preSkew / postSkew | kx, ky | Înclinare (deplasare) de-a lungul axelor |
Translate modifică poziția tuturor punctelor cu deplasarea dată dx, dy. dx pozitiv deplasează la dreapta, dy — în jos (în sistemul de coordonate al ecranului Android, axa Y este orientată în jos). Translate nu modifică forma obiectului — doar poziția acestuia. Este cea mai simplă și frecvent utilizată operație pentru poziționarea elementelor.
Scale modifică dimensiunea obiectului cu coeficienții sx (de-a lungul X) și sy (de-a lungul Y). Parametrii px, py specifică punctul de referință al scalării (pivot point). Dacă px, py nu sunt specificați, scalarea se efectuează relativ la originea coordonatelor (0, 0). La sx = sy, obiectul se scalează uniform. Valorile negative creează o reflexie.
Rotate rotește obiectul cu un unghi dat (în grade) în jurul punctului de referință (px, py). Valoarea pozitivă a gradelor corespunde rotirii în sensul acelor de ceasornic (spre deosebire de iOS/macOS, unde unghiul pozitiv este în sens invers acelor de ceasornic). Dacă px, py nu sunt specificați, rotirea se efectuează în jurul originii coordonatelor.
Skew (deformare) deformează obiectul înclinându-l de-a lungul axei X (kx) sau axei Y (ky). Valoarea 1.0 înclină la 45 de grade. Skew este utilizat pentru a crea efecte de înclinare, simularea unei vederi tridimensionale (pseudo-3D) și distorsionarea perspectivei.
Matrix stochează elementele matricei 3×3 într-un tablou intern de 9 valori în virgulă mobilă (float[9]). Ordinea de stocare — column-major (pe coloane), ceea ce corespunde reprezentării matematice standard. Accesul la elemente individuale se face prin constante: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X și așa mai departe.
Matricea este organizată astfel: primele două coloane (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) răspund de scalare, rotire și înclinare. A treia coloană (MTRANS_X, MTRANS_Y, MPERSP_2) — pentru deplasare și perspectivă. Pentru transformarea afină, MPERSP_0 și MPERSP_1 sunt egale cu 0, iar MPERSP_2 este egal cu 1.
Pentru obținerea valorilor matricei se utilizează getValues(float[] values), care umple un tablou de 9 elemente. Pentru setare — setValues(float[] values). Acest lucru permite manipularea directă a matricei pentru transformări personalizate complexe care depășesc metodele standard translate, scale, rotate și skew.
Matrix oferă mai multe metode pentru clasificarea stării curente. isIdentity() verifică dacă matricea este unitate. isAffine() — dacă conține doar transformări afine (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Aceste verificări sunt utile pentru optimizare: dacă matricea este unitate, transformarea poate fi omisă.
Matrix suportă mai multe categorii de operații: setare (set), pre-înmulțire (pre), post-înmulțire (post), concatenare (concat), inversare (invert) și mapare (map). Fiecare categorie își rezolvă sarcina la construirea transformărilor complexe.
preTranslate înmulțește matricea curentă la stânga cu matricea de deplasare: result = translate × current. postTranslate înmulțește la dreapta: result = current × translate. Diferența constă în ordinea aplicării: operațiile pre se aplică înaintea transformărilor curente, operațiile post — după. Similar funcționează preScale, postScale, preRotate, postRotate și preSkew, postSkew.
invert(Matrix inverse) calculează matricea inversă. Dacă matricea sursă este degenerată (determinantul este zero), se returnează false. concat(Matrix other) înmulțește matricea curentă cu matricea transmisă: set = set × other. Pentru ordinea inversă, utilizați setConcat(other, this).
mapRect(RectF rect) transformă dreptunghiul și returnează rezultatul într-un nou RectF. mapPoints(float[] dst, float[] src) transformă un tablou de puncte. mapVectors(float[] dst, float[] src) transformă vectori — fără a lua în considerare deplasarea (translate). mapRect este util pentru calcularea bounding box după transformare.
Matrix este utilizată activ în două scenarii cheie ale graficii Android: transformarea Canvas și transformarea Bitmap. În ambele cazuri, Matrix determină cum va fi modificată ieșirea grafică.
Canvas oferă metodele canvas.setMatrix(matrix) pentru înlocuirea completă a matricei curente și canvas.concat(matrix) pentru înmulțirea transformării curente cu cea transmisă. După aplicarea Matrix, tot desenul ulterior — apelurile drawBitmap, drawRect, drawPath — se execută în sistemul de coordonate transformat. Canvas păstrează, de asemenea, propria stivă de stări salvate prin save() și restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) creează un nou Bitmap cu aplicarea transformării date. Acesta este un instrument puternic pentru crearea de copii scalate, rotite sau deformate ale imaginilor fără a pierde Bitmap-ul original. Parametrul filter controlează netezirea la interpolarea pixelilor.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — o capacitate unică a Matrix, fără analog direct în CGAffineTransform. Calculează matricea care transformă punctele date dintr-un poligon în altul. La pointCount = 4, se creează o transformare prospectivă (projective) completă, permițând aplicarea Bitmap cu distorsiune de perspectivă.
Să examinăm exemple practice de utilizare a Matrix pentru transformarea graficii într-o aplicație Android în Kotlin.
Exemplul creează o Matrix pentru o transformare combinată: deplasare cu (100, 50), scalare de 1.5 ori și rotire de 45 de grade. Utilizarea postTranslate după preRotate și preScale schimbă ordinea aplicării operațiilor.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Aplicare la puncte
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Aplicare la dreptunghi
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
Exemplul demonstrează aplicarea Matrix la Canvas în onDraw pentru rotirea și scalarea unui cerc în jurul centrului său. Salvarea și restaurarea stării Canvas garantează că transformarea nu va afecta elementele de desen ulterioare.
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()
}
Exemplul utilizează setPolyToPoly pentru a crea o distorsionare de perspectivă a Bitmap. Patru puncte sursă (colțurile dreptunghiului original) sunt mapate pe patru puncte țintă care formează un trapez. Rezultatul — efectul unei imagini înclinate în spațiu.
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
)
}
Întrebări frecvente
Matrix lucrează cu transformări bidimensionale afine și prospective printr-o singură matrice 3×3. Camera (android.graphics.Camera) — este o clasă de nivel superior care simulează o cameră tridimensională: creează rotație 3D și apoi proiectează rezultatul în Matrix 2D. Camera utilizează Matrix intern.
Creați o Matrix cu postRotate(90f) și transmiteți-o în Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Rețineți că la rotirea de 90 de grade, lățimea și înălțimea rezultatului se inversează. Pentru rotirea la un unghi arbitrar poate fi necesară tăierea pentru a evita zonele goale.
Utilizați matrix.invert(resultMatrix). Metoda returnează true dacă inversarea este reușită și scrie matricea inversă în resultMatrix. Inversarea poate fi imposibilă dacă matricea este degenerată (de exemplu, la scalare zero). Verificați întotdeauna valoarea returnată.
pre înmulțește noua transformare la stânga: result = operation × current — operația se aplică înaintea celor curente. post înmulțește la dreapta: result = current × operation — operația se aplică după cele curente. Pentru secvența preRotate + postTranslate: mai întâi rotirea, apoi deplasarea.
Da, Matrix este utilizat în Jetpack Compose prin clasa android.graphics.Matrix în interacțiunea cu Canvas Compose. În Compose sunt disponibile graphicsLayer pentru transformare (scale, rotationX, translationX și altele), dar pentru transformări complexe ale Bitmap, Matrix se aplică în codul drawWithContent sau drawBehind.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și