Matrix — είναι μια κλάση από το Android SDK (android.graphics.Matrix) που αντιπροσωπεύει έναν συγγενικό μετασχηματισμό μέσω ενός πίνακα 3×3. Χρησιμοποιείται για τον μετασχηματισμό γραφικών αντικειμένων — μετακίνηση, κλιμάκωση, περιστροφή και κλίση. Σύμφωνα με το Android Developers Documentation (2026), το Matrix είναι το κύριο εργαλείο για εργασία με μετασχηματισμούς σε Canvas, Bitmap και Drawable, παρέχοντας ακριβή έλεγχο συντεταγμένων σε προσαρμοσμένη σχεδίαση.
Κύρια σημεία
Matrix (android.graphics.Matrix) — είναι μια κλάση Android SDK που αντιπροσωπεύει έναν μαθηματικό πίνακα 3×3 που χρησιμοποιείται για τον μετασχηματισμό δισδιάστατων συντεταγμένων. Το Matrix είναι το θεμελιώδες δομικό στοιχείο για όλους τους γραφικούς μετασχηματισμούς στο Android — από τη μετακίνηση και κλιμάκωση του Canvas έως τις σύνθετες προοπτικές παραμορφώσεις του Bitmap.
Σε αντίθεση με το iOS, όπου χρησιμοποιούνται ξεχωριστές δομές CGAffineTransform (συγγενικές) και CATransform3D (3D), το Android συνδυάζει συγγενικούς και προοπτικούς μετασχηματισμούς σε μία κλάση Matrix. Ο πίνακας 3×3 επιτρέπει την αναπαράσταση τόσο τυπικών συγγενικών λειτουργιών (τελευταία σειρά [0, 0, 1]) όσο και προοπτικών παραμορφώσεων όταν η τελευταία σειρά περιέχει αυθαίρετες τιμές. Αυτό παρέχει μεγαλύτερη ευελιξία, αλλά απαιτεί κατανόηση των μαθηματικών πινάκων.
Το Matrix είναι στενά ενσωματωμένο με το Canvas API. Όταν ο προγραμματιστής καλεί canvas.translate(), canvas.scale() ή canvas.rotate(), αυτές οι μέθοδοι εσωτερικά τροποποιούν τον πίνακα του γραφικού περιβάλλοντος. Ο τρέχων πίνακας του Canvas μπορεί να ληφθεί μέσω canvas.getMatrix(), και ένας προσαρμοσμένος πίνακας μπορεί να εφαρμοστεί χειροκίνητα μέσω canvas.setMatrix() ή canvas.concat().
Matrix υποστηρίζει τέσσερις βασικούς τύπους συγγενικών μετασχηματισμών: translate, scale, rotate, skew (κλίση). Κάθε τύπος έχει μεθόδους για προ-πολλαπλασιασμό (pre), μετα-πολλαπλασιασμό (post) και ρύθμιση (set). Η διαφορά μεταξύ preTranslate και postTranslate βρίσκεται στη σειρά πολλαπλασιασμού των πινάκων, που επηρεάζει τον τελικό μετασχηματισμό κατά τον συνδυασμό.
| Λειτουργία | Μέθοδος | Παράμετροι | Περιγραφή |
|---|---|---|---|
| Translate | setTranslate / preTranslate / postTranslate | dx, dy | Μετατόπιση κατά μήκος των αξόνων X και Y |
| Scale | setScale / preScale / postScale | sx, sy, px, py | Κλιμάκωση με σημείο αναφοράς |
| Rotate | setRotate / preRotate / postRotate | degrees, px, py | Περιστροφή γύρω από σημείο αναφοράς |
| Skew | setSkew / preSkew / postSkew | kx, ky | Κλίση (ολίσθηση) κατά μήκος αξόνων |
Translate αλλάζει τη θέση όλων των σημείων κατά τη δεδομένη μετατόπιση dx, dy. Το θετικό dx μετακινεί προς τα δεξιά, το dy — προς τα κάτω (στο σύστημα συντεταγμένων οθόνης Android ο άξονας Y είναι προς τα κάτω). Το Translate δεν αλλάζει το σχήμα του αντικειμένου — μόνο τη θέση του. Αυτή είναι η απλούστερη και πιο συχνά χρησιμοποιούμενη λειτουργία για την τοποθέτηση στοιχείων.
Scale αλλάζει το μέγεθος του αντικειμένου με συντελεστές sx (κατά μήκος X) και sy (κατά μήκος Y). Οι παράμετροι px, py καθορίζουν το σημείο αναφοράς κλιμάκωσης (pivot point). Αν δεν οριστούν px, py, η κλιμάκωση γίνεται σε σχέση με την αρχή των συντεταγμένων (0, 0). Όταν sx = sy, το αντικείμενο κλιμακώνεται ομοιόμορφα. Οι αρνητικές τιμές δημιουργούν αντανάκλαση.
Rotate περιστρέφει το αντικείμενο κατά τη δεδομένη γωνία (σε μοίρες) γύρω από το σημείο αναφοράς (px, py). Η θετική τιμή μοιρών αντιστοιχεί σε περιστροφή δεξιόστροφα (σε αντίθεση με iOS/macOS, όπου η θετική γωνία είναι αριστερόστροφα). Αν δεν οριστούν px, py, η περιστροφή γίνεται γύρω από την αρχή των συντεταγμένων.
Skew (ολίσθηση) παραμορφώνει το αντικείμενο κλίνοντάς το κατά μήκος του άξονα X (kx) ή του άξονα Y (ky). Η τιμή 1.0 κλίνει κατά 45 μοίρες. Το Skew χρησιμοποιείται για τη δημιουργία εφέ κλίσης, προσομοίωση τρισδιάστατης όψης (pseudo-3D) και παραμόρφωση προοπτικής.
Matrix αποθηκεύει τα στοιχεία του πίνακα 3×3 σε έναν εσωτερικό πίνακα 9 τιμών κινητής υποδιαστολής (float[9]). Η σειρά αποθήκευσης είναι column-major (ανά στήλη), που αντιστοιχεί στην τυπική μαθηματική αναπαράσταση. Η πρόσβαση σε μεμονωμένα στοιχεία γίνεται μέσω σταθερών: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X και ούτω καθεξής.
Ο πίνακας οργανώνεται ως εξής: οι πρώτες δύο στήλες (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) είναι υπεύθυνες για κλιμάκωση, περιστροφή και κλίση. Η τρίτη στήλη (MTRANS_X, MTRANS_Y, MPERSP_2) — για μετατόπιση και προοπτική. Για συγγενικό μετασχηματισμό, τα MPERSP_0 και MPERSP_1 είναι ίσα με 0, και το MPERSP_2 είναι ίσο με 1.
Για τη λήψη τιμών του πίνακα χρησιμοποιείται η getValues(float[] values), η οποία γεμίζει έναν πίνακα 9 στοιχείων. Για ρύθμιση — setValues(float[] values). Αυτό επιτρέπει τον άμεσο χειρισμό του πίνακα για σύνθετους προσαρμοσμένους μετασχηματισμούς που ξεπερνούν τις τυπικές μεθόδους translate, scale, rotate και skew.
Matrix παρέχει διάφορες μεθόδους για την ταξινόμηση της τρέχουσας κατάστασης. Η isIdentity() ελέγχει αν ο πίνακας είναι μοναδιαίος. Η isAffine() — αν περιέχει μόνο συγγενικούς μετασχηματισμούς (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1). Αυτοί οι έλεγχοι είναι χρήσιμοι για βελτιστοποίηση: αν ο πίνακας είναι μοναδιαίος, ο μετασχηματισμός μπορεί να παραλειφθεί.
Matrix υποστηρίζει διάφορες κατηγορίες λειτουργιών: ρύθμιση (set), προ-πολλαπλασιασμό (pre), μετα-πολλαπλασιασμό (post), συνένωση (concat), αναστροφή (invert) και χαρτογράφηση (map). Κάθε κατηγορία λύνει το δικό της έργο κατά την κατασκευή σύνθετων μετασχηματισμών.
preTranslate πολλαπλασιάζει τον τρέχοντα πίνακα από αριστερά με τον πίνακα μετατόπισης: result = translate × current. postTranslate πολλαπλασιάζει από δεξιά: result = current × translate. Η διαφορά είναι στη σειρά εφαρμογής: οι pre-λειτουργίες εφαρμόζονται πριν από τους τρέχοντες μετασχηματισμούς, οι post-λειτουργίες — μετά. Ανάλογα λειτουργούν οι preScale, postScale, preRotate, postRotate και preSkew, postSkew.
invert(Matrix inverse) υπολογίζει τον αντίστροφο πίνακα. Αν ο πίνακας προέλευσης είναι εκφυλισμένος (η ορίζουσα είναι μηδέν), επιστρέφεται false. concat(Matrix other) πολλαπλασιάζει τον τρέχοντα πίνακα με τον δοθέντα: set = set × other. Για αντίστροφη σειρά, χρησιμοποιήστε setConcat(other, this).
mapRect(RectF rect) μετασχηματίζει το ορθογώνιο και επιστρέφει το αποτέλεσμα σε ένα νέο RectF. mapPoints(float[] dst, float[] src) μετασχηματίζει έναν πίνακα σημείων. mapVectors(float[] dst, float[] src) μετασχηματίζει διανύσματα — χωρίς να λαμβάνει υπόψη τη μετατόπιση (translate). Το mapRect είναι χρήσιμο για τον υπολογισμό του bounding box μετά από μετασχηματισμό.
Matrix χρησιμοποιείται ενεργά σε δύο βασικά σενάρια γραφικών Android: μετασχηματισμός Canvas και μετασχηματισμός Bitmap. Και στις δύο περιπτώσεις, το Matrix καθορίζει πώς θα αλλάξει η γραφική έξοδος.
Canvas παρέχει μεθόδους canvas.setMatrix(matrix) για πλήρη αντικατάσταση του τρέχοντος πίνακα και canvas.concat(matrix) για πολλαπλασιασμό του τρέχοντος μετασχηματισμού με τον δοθέντα. Μετά την εφαρμογή Matrix, όλη η επακόλουθη σχεδίαση — κλήσεις drawBitmap, drawRect, drawPath — εκτελείται στο μετασχηματισμένο σύστημα συντεταγμένων. Το Canvas διατηρεί επίσης τη δική του στοίβα αποθηκευμένων καταστάσεων μέσω save() και restore().
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) δημιουργεί ένα νέο Bitmap με εφαρμογή του δεδομένου μετασχηματισμού. Αυτό είναι ένα ισχυρό εργαλείο για τη δημιουργία κλιμακωμένων, περιστραμμένων ή παραμορφωμένων αντιγράφων εικόνων χωρίς απώλεια του αρχικού Bitmap. Η παράμετρος filter ελέγχει την εξομάλυνση κατά τη παρεμβολή εικονοστοιχείων.
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — μια μοναδική δυνατότητα του Matrix, χωρίς άμεσο ανάλογο στο CGAffineTransform. Υπολογίζει έναν πίνακα που μετασχηματίζει δεδομένα σημεία από ένα πολύγωνο σε άλλο. Με pointCount = 4, δημιουργείται ένας πλήρης προοπτικός (projective) μετασχηματισμός, επιτρέποντας την εφαρμογή Bitmap με παραμόρφωση προοπτικής.
Ας εξετάσουμε πρακτικά παραδείγματα χρήσης του Matrix για μετασχηματισμό γραφικών σε μια εφαρμογή Android σε Kotlin.
Το παράδειγμα δημιουργεί ένα Matrix για συνδυασμένο μετασχηματισμό: μετατόπιση κατά (100, 50), κλιμάκωση 1.5 φορές και περιστροφή 45 μοιρών. Η χρήση postTranslate μετά από preRotate και preScale αλλάζει τη σειρά εφαρμογής των λειτουργιών.
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// Εφαρμογή σε σημεία
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// Εφαρμογή σε ορθογώνιο
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
Το παράδειγμα δείχνει εφαρμογή Matrix στο Canvas στο onDraw για περιστροφή και κλιμάκωση ενός κύκλου γύρω από το κέντρο του. Η αποθήκευση και επαναφορά της κατάστασης Canvas εγγυάται ότι ο μετασχηματισμός δεν θα επηρεάσει τα επόμενα στοιχεία σχεδίασης.
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()
}
Το παράδειγμα χρησιμοποιεί setPolyToPoly για τη δημιουργία προοπτικής παραμόρφωσης Bitmap. Τέσσερα σημεία προέλευσης (γωνίες του αρχικού ορθογωνίου) αντιστοιχίζονται σε τέσσερα σημεία προορισμού που σχηματίζουν ένα τραπέζιο. Το αποτέλεσμα — ένα εφέ εικόνας με κλίση στον χώρο.
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
)
}
Συχνές Ερωτήσεις
Matrix λειτουργεί με δισδιάστατους συγγενικούς και προοπτικούς μετασχηματισμούς μέσω ενός πίνακα 3×3. Camera (android.graphics.Camera) — είναι μια κλάση υψηλότερου επιπέδου που προσομοιώνει μια τρισδιάστατη κάμερα: δημιουργεί 3D περιστροφή και στη συνέχεια προβάλλει το αποτέλεσμα σε 2D Matrix. Η Camera χρησιμοποιεί το Matrix εσωτερικά.
Δημιουργήστε ένα Matrix με postRotate(90f) και μεταβιβάστε το σε Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Λάβετε υπόψη ότι κατά την περιστροφή 90 μοιρών, το πλάτος και το ύψος του αποτελέσματος ανταλλάσσονται. Για περιστροφή σε αυθαίρετη γωνία μπορεί να απαιτηθεί περικοπή για να αποφευχθούν κενές περιοχές.
Χρησιμοποιήστε matrix.invert(resultMatrix). Η μέθοδος επιστρέφει true αν η αναστροφή είναι επιτυχής και γράφει τον αντίστροφο πίνακα στο resultMatrix. Η αναστροφή μπορεί να είναι αδύνατη αν ο πίνακας είναι εκφυλισμένος (π.χ., σε μηδενική κλίμακα). Πάντα ελέγχετε την τιμή επιστροφής.
pre πολλαπλασιάζει τον νέο μετασχηματισμό από αριστερά: result = operation × current — η λειτουργία εφαρμόζεται πριν από τους τρέχοντες μετασχηματισμούς. post πολλαπλασιάζει από δεξιά: result = current × operation — η λειτουργία εφαρμόζεται μετά. Για την ακολουθία preRotate + postTranslate: πρώτα περιστροφή, μετά μετατόπιση.
Ναι, το Matrix χρησιμοποιείται στο Jetpack Compose μέσω της κλάσης android.graphics.Matrix σε αλληλεπίδραση με το Canvas Compose. Στο Compose, το graphicsLayer είναι διαθέσιμο για μετασχηματισμό (scale, rotationX, translationX και άλλα), αλλά για σύνθετους μετασχηματισμούς Bitmap, το Matrix εφαρμόζεται στον κώδικα drawWithContent ή drawBehind.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης