Matrix — eine Klasse aus dem Android SDK (android.graphics.Matrix), die eine affine Transformation durch eine 3×3-Matrix darstellt. Sie wird zur Transformation von Grafikobjekten verwendet — Verschieben, Skalieren, Drehen und Neigen. Laut Android Developers Documentation (2026) ist Matrix das wichtigste Werkzeug für Transformationen in Canvas, Bitmap und Drawable und bietet eine präzise Koordinatensteuerung beim benutzerdefinierten Zeichnen.
Wichtige Punkte
Matrix (android.graphics.Matrix) — eine Klasse des Android SDK, die eine mathematische 3×3-Matrix zur Transformation zweidimensionaler Koordinaten darstellt. Matrix ist der grundlegende Baustein für alle grafischen Transformationen in Android — von der Bewegung und Skalierung von Canvas bis zu komplexen perspektivischen Verzerrungen von Bitmap.
Im Gegensatz zu iOS, das separate Strukturen CGAffineTransform (affin) und CATransform3D (3D) verwendet, vereint Android affine und perspektivische Transformationen in einer einzigen Matrix-Klasse. Die 3×3-Matrix ermöglicht die Darstellung sowohl von Standard-Affin-Operationen (letzte Zeile [0, 0, 1]) als auch von perspektivischen Verzerrungen, bei denen die letzte Zeile beliebige Werte enthält. Dies bietet mehr Flexibilität, erfordert jedoch ein Verständnis der Matrix-Mathematik.
Matrix ist eng in die Canvas-API integriert. Wenn ein Entwickler canvas.translate(), canvas.scale() oder canvas.rotate() aufruft, ändern diese Methoden intern die Matrix des Grafik-Kontexts. Die aktuelle Canvas-Matrix kann über canvas.getMatrix() abgerufen werden, und eine benutzerdefinierte Matrix kann manuell über canvas.setMatrix() oder canvas.concat() angewendet werden.
Matrix unterstützt vier grundlegende Arten von affinen Transformationen: translate, scale, rotate, skew (neigen). Jeder Typ hat Methoden für Vormultiplikation (pre), Nachmultiplikation (post) und Setzen (set). Der Unterschied zwischen preTranslate und postTranslate liegt in der Reihenfolge der Matrix-Multiplikation, die die endgültige Transformation beim Kombinieren von Operationen beeinflusst.
| Operation | Methode | Parameter | Beschreibung |
|---|---|---|---|
| Verschieben | setTranslate / preTranslate / postTranslate | dx, dy | Verschiebung entlang der X- und Y-Achsen |
| Skalieren | setScale / preScale / postScale | sx, sy, px, py | Skalierung mit Drehpunkt |
| Drehen | setRotate / preRotate / postRotate | degrees, px, py | Drehung um den Drehpunkt |
| Neigen | setSkew / preSkew / postSkew | kx, ky | Neigung (Scherung) entlang der Achsen |
Translate ändert die Position aller Punkte um eine bestimmte Verschiebung dx, dy. Positives dx verschiebt nach rechts, dy — nach unten (im Android-Bildschirmkoordinatensystem zeigt die Y-Achse nach unten). Translate ändert die Form des Objekts nicht — nur seine Position. Dies ist die einfachste und am häufigsten verwendete Operation zum Positionieren von Elementen.
Scale ändert die Größe eines Objekts mit den Faktoren sx (entlang X) und sy (entlang Y). Die Parameter px, py geben den Drehpunkt für die Skalierung an. Wenn px, py nicht angegeben sind, wird die Skalierung relativ zum Ursprung (0, 0) durchgeführt. Bei sx = sy wird das Objekt gleichmäßig skaliert. Negative Werte erzeugen eine Spiegelung.
Rotate dreht ein Objekt um einen bestimmten Winkel (in Grad) um einen Drehpunkt (px, py). Positive Gradwerte entsprechen einer Drehung im Uhrzeigersinn (im Gegensatz zu iOS/macOS, wo ein positiver Winkel gegen den Uhrzeigersinn ist). Wenn px, py nicht angegeben sind, wird die Drehung um den Ursprung durchgeführt.
Skew (Scherung) verformt ein Objekt, indem es entlang der X-Achse (kx) oder Y-Achse (ky) geneigt wird. Ein Wert von 1.0 neigt um 45 Grad. Skew wird verwendet, um Neigungseffekte, Pseudo-3D-Erscheinungen und perspektivische Verzerrungen zu erzeugen.
Matrix speichert ihre 3×3-Elemente in einem internen Array von 9 Gleitkommawerten (float[9]). Die Speicherreihenfolge ist spaltenweise (column-major), entsprechend der mathematischen Standarddarstellung. Der Zugriff auf einzelne Elemente erfolgt über Konstanten: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X und so weiter.
Die Matrix ist wie folgt organisiert: Die ersten beiden Spalten (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) sind für Skalierung, Drehung und Neigung zuständig. Die dritte Spalte (MTRANS_X, MTRANS_Y, MPERSP_2) ist für Verschiebung und Perspektive zuständig. Bei affinen Transformationen sind MPERSP_0 und MPERSP_1 gleich 0, und MPERSP_2 ist 1.
Zum Abrufen der Matrixwerte verwenden Sie getValues(float[] values), das ein Array mit 9 Elementen füllt. Zum Setzen verwenden Sie setValues(float[] values). Dies ermöglicht die direkte Manipulation der Matrix für komplexe benutzerdefinierte Transformationen, die über die Standardmethoden translate, scale, rotate und skew hinausgehen.
Matrix bietet mehrere Methoden zur Klassifizierung des aktuellen Zustands. isIdentity() prüft, ob die Matrix eine Einheitsmatrix ist. isAffine() prüft, ob sie nur affine Transformationen enthält (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Diese Prüfungen sind für die Optimierung nützlich: Wenn die Matrix eine Einheitsmatrix ist, kann die Transformation übersprungen werden.
Matrix unterstützt mehrere Kategorien von Operationen: Setzen (set), Vormultiplikation (pre), Nachmultiplikation (post), Konkatenation (concat), Inversion (invert) und Mapping (map). Jede Kategorie hat ihren Zweck beim Aufbau komplexer Transformationen.
preTranslate multipliziert die aktuelle Matrix von links mit der Verschiebungsmatrix: result = translate × current. postTranslate multipliziert von rechts: result = current × translate. Der Unterschied liegt in der Reihenfolge der Anwendung: Pre-Operationen werden vor den aktuellen Transformationen angewendet, Post-Operationen danach. Gleiches gilt für preScale, postScale, preRotate, postRotate und preSkew, postSkew.
invert(Matrix inverse) berechnet die inverse Matrix. Wenn die ursprüngliche Matrix singulär ist (Determinante ist Null), wird false zurückgegeben. concat(Matrix other) multipliziert die aktuelle Matrix mit der übergebenen: set = set × other. Für die umgekehrte Reihenfolge verwenden Sie setConcat(other, this).
mapRect(RectF rect) transformiert ein Rechteck und gibt das Ergebnis in einem neuen RectF zurück. mapPoints(float[] dst, float[] src) transformiert ein Array von Punkten. mapVectors(float[] dst, float[] src) transformiert Vektoren — ohne Berücksichtigung der Verschiebung. mapRect ist nützlich zur Berechnung von Begrenzungsrahmen nach der Transformation.
Matrix wird aktiv in zwei wichtigen Android-Grafikszenarien eingesetzt: Canvas-Transformation und Bitmap-Transformation. In beiden Fällen bestimmt Matrix, wie die grafische Ausgabe verändert wird.
Canvas bietet canvas.setMatrix(matrix) zum vollständigen Ersetzen der aktuellen Matrix und canvas.concat(matrix) zum Multiplizieren der aktuellen Transformation mit der übergebenen. Nach dem Anwenden von Matrix erfolgt das gesamte nachfolgende Zeichnen — drawBitmap-, drawRect-, drawPath-Aufrufe — im transformierten Koordinatensystem. Canvas verwaltet auch einen eigenen Stapel gespeicherter Zustände über save() und restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) erstellt ein neues Bitmap mit der angegebenen Transformation. Dies ist ein leistungsstarkes Werkzeug zum Erstellen skalierter, gedrehter oder verzerrter Bildkopien, ohne das ursprüngliche Bitmap zu verlieren. Der Parameter filter steuert das Anti-Aliasing bei der Pixelinterpolation.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — eine einzigartige Fähigkeit von Matrix ohne direktes Äquivalent in CGAffineTransform. Sie berechnet eine Matrix, die bestimmte Punkte von einem Polygon in ein anderes transformiert. Bei pointCount = 4 wird eine vollständige perspektivische (projektive) Transformation erstellt, die das Überlagern von Bitmap mit perspektivischer Verzerrung ermöglicht.
Schauen wir uns praktische Beispiele zur Verwendung von Matrix für die Grafiktransformation in einer Android-Anwendung mit Kotlin an.
Das Beispiel erstellt eine Matrix für eine kombinierte Transformation: Verschiebung um (100, 50), Skalierung um das 1,5-fache und Drehung um 45 Grad. Die Verwendung von postTranslate nach preRotate und preScale ändert die Reihenfolge der Operationsanwendung.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Auf Punkte anwenden
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Auf Rechteck anwenden
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
Das Beispiel demonstriert die Anwendung von Matrix auf Canvas in onDraw, um einen Kreis um seinen Mittelpunkt zu drehen und zu skalieren. Das Speichern und Wiederherstellen des Canvas-Zustands stellt sicher, dass die Transformation nachfolgende Zeichenelemente nicht beeinflusst.
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()
}
Das Beispiel verwendet setPolyToPoly, um eine perspektivische Verzerrung eines Bitmap zu erzeugen. Vier Quellpunkte (Ecken des ursprünglichen Rechtecks) werden auf vier Zielpunkte abgebildet, die ein Trapez bilden. Das Ergebnis ist ein Effekt eines im Raum geneigten Bildes.
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
)
}
Häufig gestellte Fragen
Matrix arbeitet mit zweidimensionalen affinen und perspektivischen Transformationen über eine einzige 3×3-Matrix. Camera (android.graphics.Camera) ist eine höherwertige Klasse, die eine dreidimensionale Kamera simuliert: Sie erzeugt eine 3D-Drehung und projiziert das Ergebnis dann in eine 2D-Matrix. Camera verwendet Matrix intern.
Erstellen Sie eine Matrix mit postRotate(90f) und übergeben Sie sie an Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Beachten Sie, dass bei einer Drehung um 90 Grad die Breite und Höhe des Ergebnisses vertauscht werden. Bei Drehung um einen beliebigen Winkel kann ein Zuschneiden erforderlich sein, um leere Bereiche zu vermeiden.
Verwenden Sie matrix.invert(resultMatrix). Die Methode gibt true zurück, wenn die Inversion erfolgreich ist, und schreibt die inverse Matrix in resultMatrix. Die Inversion kann unmöglich sein, wenn die Matrix singulär ist (z. B. bei Null-Skalierung). Überprüfen Sie immer den Rückgabewert.
pre multipliziert die neue Transformation von links: result = operation × current — die Operation wird vor den aktuellen angewendet. post multipliziert von rechts: result = current × operation — die Operation wird danach angewendet. Für eine Sequenz preRotate + postTranslate: zuerst Drehung, dann Verschiebung.
Ja, Matrix wird in Jetpack Compose über die Klasse android.graphics.Matrix in der Interaktion mit Canvas Compose verwendet. In Compose steht graphicsLayer für Transformationen (scale, rotationX, translationX und andere) zur Verfügung, aber für komplexe Bitmap-Transformationen wird Matrix im drawWithContent- oder drawBehind-Code verwendet.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch