Matrix στο Android: τι είναι, τύποι πινάκων και εργασία με μετασχηματισμούς

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-22 Χρόνος ανάγνωσης: 9 λεπ

Matrix — είναι μια κλάση από το Android SDK (android.graphics.Matrix) που αντιπροσωπεύει έναν συγγενικό μετασχηματισμό μέσω ενός πίνακα 3×3. Χρησιμοποιείται για τον μετασχηματισμό γραφικών αντικειμένων — μετακίνηση, κλιμάκωση, περιστροφή και κλίση. Σύμφωνα με το Android Developers Documentation (2026), το Matrix είναι το κύριο εργαλείο για εργασία με μετασχηματισμούς σε Canvas, Bitmap και Drawable, παρέχοντας ακριβή έλεγχο συντεταγμένων σε προσαρμοσμένη σχεδίαση.

Κύρια σημεία

  • Matrix — κλάση Android για συγγενικούς και προοπτικούς μετασχηματισμούς με πίνακα 3×3
  • Συγγενικές λειτουργίες: translate (μετατόπιση), scale (κλίμακα), rotate (περιστροφή) και skew (κλίση)
  • Το Matrix υποστηρίζει προοπτικούς (projective) μετασχηματισμούς μέσω setPolyToPoly
  • Η σειρά εφαρμογής των λειτουργιών είναι σημαντική — Matrix.concat εκτελεί διαδοχικό πολλαπλασιασμό
  • Το Matrix εφαρμόζεται σε Canvas, Bitmap, RectF, PointF και Path στα γραφικά Android

Τι είναι το Matrix στο Android;

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

Matrix υποστηρίζει τέσσερις βασικούς τύπους συγγενικών μετασχηματισμών: translate, scale, rotate, skew (κλίση). Κάθε τύπος έχει μεθόδους για προ-πολλαπλασιασμό (pre), μετα-πολλαπλασιασμό (post) και ρύθμιση (set). Η διαφορά μεταξύ preTranslate και postTranslate βρίσκεται στη σειρά πολλαπλασιασμού των πινάκων, που επηρεάζει τον τελικό μετασχηματισμό κατά τον συνδυασμό.

ΛειτουργίαΜέθοδοςΠαράμετροιΠεριγραφή
TranslatesetTranslate / preTranslate / postTranslatedx, dyΜετατόπιση κατά μήκος των αξόνων X και Y
ScalesetScale / preScale / postScalesx, sy, px, pyΚλιμάκωση με σημείο αναφοράς
RotatesetRotate / preRotate / postRotatedegrees, px, pyΠεριστροφή γύρω από σημείο αναφοράς
SkewsetSkew / preSkew / postSkewkx, kyΚλίση (ολίσθηση) κατά μήκος αξόνων

Translate — μετατόπιση

Translate αλλάζει τη θέση όλων των σημείων κατά τη δεδομένη μετατόπιση dx, dy. Το θετικό dx μετακινεί προς τα δεξιά, το dy — προς τα κάτω (στο σύστημα συντεταγμένων οθόνης Android ο άξονας Y είναι προς τα κάτω). Το Translate δεν αλλάζει το σχήμα του αντικειμένου — μόνο τη θέση του. Αυτή είναι η απλούστερη και πιο συχνά χρησιμοποιούμενη λειτουργία για την τοποθέτηση στοιχείων.

Scale — κλιμάκωση

Scale αλλάζει το μέγεθος του αντικειμένου με συντελεστές sx (κατά μήκος X) και sy (κατά μήκος Y). Οι παράμετροι px, py καθορίζουν το σημείο αναφοράς κλιμάκωσης (pivot point). Αν δεν οριστούν px, py, η κλιμάκωση γίνεται σε σχέση με την αρχή των συντεταγμένων (0, 0). Όταν sx = sy, το αντικείμενο κλιμακώνεται ομοιόμορφα. Οι αρνητικές τιμές δημιουργούν αντανάκλαση.

Rotate — περιστροφή

Rotate περιστρέφει το αντικείμενο κατά τη δεδομένη γωνία (σε μοίρες) γύρω από το σημείο αναφοράς (px, py). Η θετική τιμή μοιρών αντιστοιχεί σε περιστροφή δεξιόστροφα (σε αντίθεση με iOS/macOS, όπου η θετική γωνία είναι αριστερόστροφα). Αν δεν οριστούν px, py, η περιστροφή γίνεται γύρω από την αρχή των συντεταγμένων.

Skew — κλίση

Skew (ολίσθηση) παραμορφώνει το αντικείμενο κλίνοντάς το κατά μήκος του άξονα X (kx) ή του άξονα Y (ky). Η τιμή 1.0 κλίνει κατά 45 μοίρες. Το Skew χρησιμοποιείται για τη δημιουργία εφέ κλίσης, προσομοίωση τρισδιάστατης όψης (pseudo-3D) και παραμόρφωση προοπτικής.

Δομή του πίνακα 3×3

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

Matrix υποστηρίζει διάφορες κατηγορίες λειτουργιών: ρύθμιση (set), προ-πολλαπλασιασμό (pre), μετα-πολλαπλασιασμό (post), συνένωση (concat), αναστροφή (invert) και χαρτογράφηση (map). Κάθε κατηγορία λύνει το δικό της έργο κατά την κατασκευή σύνθετων μετασχηματισμών.

Λειτουργίες Pre και Post

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).

Map — εφαρμογή σε σημεία και ορθογώνια

mapRect(RectF rect) μετασχηματίζει το ορθογώνιο και επιστρέφει το αποτέλεσμα σε ένα νέο RectF. mapPoints(float[] dst, float[] src) μετασχηματίζει έναν πίνακα σημείων. mapVectors(float[] dst, float[] src) μετασχηματίζει διανύσματα — χωρίς να λαμβάνει υπόψη τη μετατόπιση (translate). Το mapRect είναι χρήσιμο για τον υπολογισμό του bounding box μετά από μετασχηματισμό.

Εφαρμογή σε Canvas και Bitmap

Matrix χρησιμοποιείται ενεργά σε δύο βασικά σενάρια γραφικών Android: μετασχηματισμός Canvas και μετασχηματισμός Bitmap. Και στις δύο περιπτώσεις, το Matrix καθορίζει πώς θα αλλάξει η γραφική έξοδος.

Μετασχηματισμός Canvas μέσω Matrix

Canvas παρέχει μεθόδους canvas.setMatrix(matrix) για πλήρη αντικατάσταση του τρέχοντος πίνακα και canvas.concat(matrix) για πολλαπλασιασμό του τρέχοντος μετασχηματισμού με τον δοθέντα. Μετά την εφαρμογή Matrix, όλη η επακόλουθη σχεδίαση — κλήσεις drawBitmap, drawRect, drawPath — εκτελείται στο μετασχηματισμένο σύστημα συντεταγμένων. Το Canvas διατηρεί επίσης τη δική του στοίβα αποθηκευμένων καταστάσεων μέσω save() και restore().

Μετασχηματισμός Bitmap μέσω Matrix

Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) δημιουργεί ένα νέο Bitmap με εφαρμογή του δεδομένου μετασχηματισμού. Αυτό είναι ένα ισχυρό εργαλείο για τη δημιουργία κλιμακωμένων, περιστραμμένων ή παραμορφωμένων αντιγράφων εικόνων χωρίς απώλεια του αρχικού Bitmap. Η παράμετρος filter ελέγχει την εξομάλυνση κατά τη παρεμβολή εικονοστοιχείων.

setPolyToPoly — προοπτικοί μετασχηματισμοί

setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — μια μοναδική δυνατότητα του Matrix, χωρίς άμεσο ανάλογο στο CGAffineTransform. Υπολογίζει έναν πίνακα που μετασχηματίζει δεδομένα σημεία από ένα πολύγωνο σε άλλο. Με pointCount = 4, δημιουργείται ένας πλήρης προοπτικός (projective) μετασχηματισμός, επιτρέποντας την εφαρμογή Bitmap με παραμόρφωση προοπτικής.

Παραδείγματα κώδικα σε Kotlin

Ας εξετάσουμε πρακτικά παραδείγματα χρήσης του Matrix για μετασχηματισμό γραφικών σε μια εφαρμογή Android σε Kotlin.

Βασικοί συγγενικοί μετασχηματισμοί

Το παράδειγμα δημιουργεί ένα Matrix για συνδυασμένο μετασχηματισμό: μετατόπιση κατά (100, 50), κλιμάκωση 1.5 φορές και περιστροφή 45 μοιρών. Η χρήση postTranslate μετά από preRotate και preScale αλλάζει τη σειρά εφαρμογής των λειτουργιών.

kotlin
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)

Μετασχηματισμός Canvas με save και restore

Το παράδειγμα δείχνει εφαρμογή Matrix στο Canvas στο onDraw για περιστροφή και κλιμάκωση ενός κύκλου γύρω από το κέντρο του. Η αποθήκευση και επαναφορά της κατάστασης Canvas εγγυάται ότι ο μετασχηματισμός δεν θα επηρεάσει τα επόμενα στοιχεία σχεδίασης.

kotlin
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

Το παράδειγμα χρησιμοποιεί setPolyToPoly για τη δημιουργία προοπτικής παραμόρφωσης Bitmap. Τέσσερα σημεία προέλευσης (γωνίες του αρχικού ορθογωνίου) αντιστοιχίζονται σε τέσσερα σημεία προορισμού που σχηματίζουν ένα τραπέζιο. Το αποτέλεσμα — ένα εφέ εικόνας με κλίση στον χώρο.

kotlin
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 από το Camera στο Android;

Matrix λειτουργεί με δισδιάστατους συγγενικούς και προοπτικούς μετασχηματισμούς μέσω ενός πίνακα 3×3. Camera (android.graphics.Camera) — είναι μια κλάση υψηλότερου επιπέδου που προσομοιώνει μια τρισδιάστατη κάμερα: δημιουργεί 3D περιστροφή και στη συνέχεια προβάλλει το αποτέλεσμα σε 2D Matrix. Η Camera χρησιμοποιεί το Matrix εσωτερικά.

Πώς να περιστρέψετε Bitmap κατά 90 μοίρες;

Δημιουργήστε ένα Matrix με postRotate(90f) και μεταβιβάστε το σε Bitmap.createBitmap(original, 0, 0, w, h, matrix, true). Λάβετε υπόψη ότι κατά την περιστροφή 90 μοιρών, το πλάτος και το ύψος του αποτελέσματος ανταλλάσσονται. Για περιστροφή σε αυθαίρετη γωνία μπορεί να απαιτηθεί περικοπή για να αποφευχθούν κενές περιοχές.

Πώς να λάβετε τον αντίστροφο μετασχηματισμό του Matrix;

Χρησιμοποιήστε matrix.invert(resultMatrix). Η μέθοδος επιστρέφει true αν η αναστροφή είναι επιτυχής και γράφει τον αντίστροφο πίνακα στο resultMatrix. Η αναστροφή μπορεί να είναι αδύνατη αν ο πίνακας είναι εκφυλισμένος (π.χ., σε μηδενική κλίμακα). Πάντα ελέγχετε την τιμή επιστροφής.

Ποια είναι η διαφορά μεταξύ pre και post λειτουργιών;

pre πολλαπλασιάζει τον νέο μετασχηματισμό από αριστερά: result = operation × current — η λειτουργία εφαρμόζεται πριν από τους τρέχοντες μετασχηματισμούς. post πολλαπλασιάζει από δεξιά: result = current × operation — η λειτουργία εφαρμόζεται μετά. Για την ακολουθία preRotate + postTranslate: πρώτα περιστροφή, μετά μετατόπιση.

Μπορεί να χρησιμοποιηθεί το Matrix στο Compose;

Ναι, το Matrix χρησιμοποιείται στο Jetpack Compose μέσω της κλάσης android.graphics.Matrix σε αλληλεπίδραση με το Canvas Compose. Στο Compose, το graphicsLayer είναι διαθέσιμο για μετασχηματισμό (scale, rotationX, translationX και άλλα), αλλά για σύνθετους μετασχηματισμούς Bitmap, το Matrix εφαρμόζεται στον κώδικα drawWithContent ή drawBehind.

Σύνοψη

  • Matrix — κλάση Android για συγγενικούς και προοπτικούς μετασχηματισμούς με πίνακα 3×3
  • Τέσσερις βασικοί τύποι: translate (μετατόπιση), scale (κλίμακα), rotate (περιστροφή), skew (κλίση)
  • Λειτουργίες pre/post ελέγχουν τη σειρά εφαρμογής: pre — πριν από τους τρέχοντες μετασχηματισμούς, post — μετά τους τρέχοντες μετασχηματισμούς
  • setPolyToPoly — μοναδική συνάρτηση για υπολογισμό προοπτικού μετασχηματισμού για 4 ζεύγη σημείων
  • Το Matrix εφαρμόζεται σε Canvas μέσω concat, σε Bitmap μέσω createBitmap με Matrix, σε σημεία μέσω mapPoints
  • invert υπολογίζει τον αντίστροφο μετασχηματισμό, επιστρέφοντας false για εκφυλισμένους πίνακες
  • isAffine και isIdentity βοηθούν στην ταξινόμηση της κατάστασης του πίνακα για βελτιστοποίηση

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης