Canvas στο Android: τι είναι, κλάση Canvas και μέθοδοι draw

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

Canvas στο Android — είναι μια κλάση από το πακέτο android.graphics που παρέχει API για 2D σχεδίαση σε View. Το Canvas λειτουργεί σαν καμβάς, πάνω στον οποίο ο προγραμματιστής σχεδιάζει γεωμετρικά σχήματα, κείμενο, εικόνες και διαδρομές χρησιμοποιώντας διάφορες μεθόδους draw*. Σύμφωνα με το Android Developers Documentation (2025), το Canvas είναι το κύριο εργαλείο για προσαρμοσμένη σχεδίαση στο Android και χρησιμοποιείται μαζί με την κλάση Paint για τον καθορισμό στυλ και χρωμάτων. Κάθε κλήση onDraw() λαμβάνει ένα έτοιμο στιγμιότυπο Canvas που συνδέεται με το buffer bitmap της προβολής.

Κύρια σημεία

  • Canvas — κλάση για 2D σχεδίαση στο Android, παρέχει μεθόδους drawRect, drawCircle, drawText, drawBitmap και άλλες
  • Paint — κλάση που καθορίζει το στυλ σχεδίασης: χρώμα, πάχος, γέμισμα, εφέ (σκιά, κλίση)
  • onDraw(Canvas) — μέθοδος View στην οποία γίνεται όλη η σχεδίαση μέσω του ληφθέντος Canvas
  • Canvas.save() και restore() — διαχείριση στοίβας μετασχηματισμών για ένθετους μετασχηματισμούς συστήματος συντεταγμένων
  • Path — κλάση για δημιουργία αυθαίρετων περιγραμμάτων και καμπύλων, μεταβιβάζεται στο drawPath(Path, Paint)

Τι είναι το Canvas στο Android

Canvas — είναι η κεντρική κλάση 2D γραφικών στο Android που παρέχει μεθόδους για σχεδίαση σε επίπεδο. Κάθε Canvas είναι συνδεδεμένο με ένα Bitmap — μια περιοχή μνήμης όπου γράφονται τα αποτελέσματα των λειτουργιών σχεδίασης. Όταν το View επανασχεδιάζεται, το σύστημα μεταβιβάζει στο onDraw() ένα Canvas που είναι ήδη συνδεδεμένο με το buffer αυτού του View.

Το Canvas λειτουργεί σε ένα σύστημα συντεταγμένων όπου (0,0) είναι η πάνω αριστερή γωνία, ο άξονας X πηγαίνει δεξιά, ο άξονας Y κάτω. Όλες οι λειτουργίες σχεδίασης χρησιμοποιούν την τρέχουσα κατάσταση του Canvas, συμπεριλαμβανομένου του πίνακα μετασχηματισμού, της περιοχής αποκοπής (clip) και του στυλ Paint. Σύμφωνα με το Android Documentation (2025), το Canvas API περιλαμβάνει πάνω από 30 μεθόδους draw* για διαφορετικούς τύπους γραφικών πρωτογόνων.

Canvas και Επιτάχυνση Υλικού

Από το Android 3.0 (API 11) το Canvas υποστηρίζει επιτάχυνση υλικού μέσω DisplayList. Στη λειτουργία επιτάχυνσης, οι λειτουργίες Canvas γράφονται στο DisplayList και στη συνέχεια εκτελούνται στην GPU. Αυτό δίνει σημαντική αύξηση απόδοσης, αλλά επιβάλλει περιορισμούς: ορισμένες λειτουργίες Canvas (clipPath με μη Path αποκοπή) δεν υποστηρίζονται στη λειτουργία επιτάχυνσης.

Βασικές μέθοδοι Canvas για σχεδίαση

Το Canvas παρέχει ένα σύνολο μεθόδων για σχεδίαση βασικών πρωτογόνων. Κάθε μέθοδος δέχεται γεωμετρικές παραμέτρους και ένα αντικείμενο Paint που καθορίζει το οπτικό στυλ.

ΜέθοδοςΣκοπόςΠαράδειγμα
drawRect()Σχεδίαση ορθογωνίουcanvas.drawRect(10f, 10f, 100f, 100f, paint)
drawCircle()Σχεδίαση κύκλουcanvas.drawCircle(50f, 50f, 30f, paint)
drawLine()Σχεδίαση γραμμήςcanvas.drawLine(0f, 0f, 100f, 100f, paint)
drawText()Σχεδίαση κειμένουcanvas.drawText("Hello", 10f, 20f, paint)
drawBitmap()Σχεδίαση εικόναςcanvas.drawBitmap(bitmap, 0f, 0f, paint)
drawPath()Σχεδίαση αυθαίρετης διαδρομήςcanvas.drawPath(path, paint)
drawOval()Σχεδίαση οβάλcanvas.drawOval(rectF, paint)
drawArc()Σχεδίαση τόξου ή τομέαcanvas.drawArc(rectF, 0f, 90f, true, paint)

Κάθε μέθοδος μπορεί να κληθεί σε οποιαδήποτε σειρά — το Canvas σχεδιάζει με τη σειρά κλήσεων, τοποθετώντας νέα στοιχεία πάνω από τα προηγούμενα. Για σύνθετες συνθέσεις χρησιμοποιείται η τεχνική πολυεπίπεδης σχεδίασης με αποθήκευση και επαναφορά της κατάστασης Canvas.

Κλάση Paint: ρύθμιση στυλ και εφέ

Paint — είναι η κλάση που καθορίζει πώς θα σχεδιάσει το Canvas. Χωρίς Paint, οι μέθοδοι Canvas είναι άχρηστες — ορίζει χρώμα, πάχος γραμμής, στυλ γεμίσματος, μέγεθος κειμένου, εφέ (σκιά, κλίση, θάμπωμα) και λειτουργία ανάμειξης.

Το Paint έχει βασικές ιδιότητες: color (χρώμα), style (FILL, STROKE ή FILL_AND_STROKE), strokeWidth (πάχος γραμμής), textSize (μέγεθος κειμένου), isAntiAlias (εξομάλυνση), shader (κλίση ή εικόνα). Η δημιουργία αντικειμένου Paint είναι μια δαπανηρή λειτουργία, επομένως πρέπει να δημιουργείται μία φορά και να επαναχρησιμοποιείται.

kotlin
private val fillPaint = Paint().apply {
    color = Color.parseColor("#FF6200EE")
    style = Paint.Style.FILL
    isAntiAlias = true
}

private val strokePaint = Paint().apply {
    color = Color.WHITE
    style = Paint.Style.STROKE
    strokeWidth = 4f
    isAntiAlias = true
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    canvas.drawCircle(100f, 100f, 80f, fillPaint)
    canvas.drawCircle(100f, 100f, 80f, strokePaint)
}

Σε αυτό το παράδειγμα χρησιμοποιούνται δύο Paint: ένα για το γέμισμα του κύκλου με μοβ χρώμα, το δεύτερο για το λευκό περίγραμμα. Ο διαχωρισμός σε fill και stroke είναι μια τυπική πρακτική που επιτρέπει την ευέλικτη διαχείριση της εμφάνισης χωρίς αναδημιουργία αντικειμένων.

Shader και κλίσεις

Για γεμίσματα με κλίση, το Paint δέχεται ένα Shader — υποκλάσεις LinearGradient, RadialGradient, SweepGradient. Το Shader συνδέεται στο Paint μέσω της μεθόδου setShader() και καθορίζει πώς αλλάζει το χρώμα στην περιοχή σχεδίασης.

Μετασχηματισμοί Canvas: translate, rotate, scale

Το Canvas υποστηρίζει μητρικούς μετασχηματισμούς του συστήματος συντεταγμένων: translate() (μετατόπιση), rotate() (περιστροφή), scale() (κλίμακα) και skew() (λοξή). Οι μετασχηματισμοί συσσωρεύονται: κάθε επόμενη κλήση εφαρμόζεται πάνω από τις προηγούμενες.

Η διαχείριση της στοίβας μετασχηματισμών γίνεται μέσω save() και restore(). Η save() αποθηκεύει την τρέχουσα κατάσταση Canvas (πίνακα, clip) στη στοίβα, η restore() επαναφέρει την τελευταία αποθηκευμένη κατάσταση. Μεταξύ save() και restore() μπορεί να υπάρχουν ένθετοι μετασχηματισμοί.

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    canvas.save() // Αποθήκευση αρχικής κατάστασης
    canvas.translate(100f, 100f) // Μετατόπιση αρχής

    // Πρώτο τετράγωνο
    canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)

    canvas.save() // Αποθήκευση μετά μετατόπιση
    canvas.rotate(45f, 25f, 25f) // Περιστροφή γύρω από κέντρο τετραγώνου

    // Περιστρεφόμενο τετράγωνο
    canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
    canvas.restore() // Επαναφορά μετά περιστροφή

    canvas.restore() // Επαναφορά αρχικής κατάστασης
}

Χρησιμοποιείτε πάντα save() πριν από την έναρξη μετασχηματισμών και restore() μετά την ολοκλήρωσή τους. Οι μη ισορροπημένες save/restore οδηγούν σε συσσώρευση του πίνακα και λανθασμένη σχεδίαση των επόμενων στοιχείων.

Canvas με Bitmap και Path για σύνθετα γραφικά

Για σύνθετα γραφικά, το Canvas συνδυάζεται με Bitmap και Path. Το Bitmap χρησιμοποιείται για φόρτωση εικόνων και προσωρινή αποθήκευση αποδοθέντων καρέ. Το Path — για δημιουργία αυθαίρετων καμπύλων Bezier, πολυγώνων και σύνθετων περιγραμμάτων.

Offscreen Bitmap buffer

Τεχνική offscreen-απόδοσης: δημιουργείται ένα Bitmap, πάνω του σχεδιάζεται μια σύνθετη σκηνή μέσω ξεχωριστού Canvas, και στη συνέχεια το έτοιμο Bitmap εμφανίζεται στο onDraw() μέσω drawBitmap(). Αυτό επιτρέπει την ενημέρωση σύνθετων γραφικών χωρίς πλήρη επανασχεδίαση κάθε καρέ.

kotlin
private var offscreenBitmap: Bitmap? = null
private var offscreenCanvas: Canvas? = null

fun buildOffscreenScene(width: Int, height: Int) {
    offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    offscreenCanvas = Canvas(offscreenBitmap)

    // Απόδοση σκηνής μία φορά
    offscreenCanvas!!.drawColor(Color.WHITE)
    drawGrid(offscreenCanvas!!)
    drawComplexShape(offscreenCanvas!!)
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    offscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}

Path χρησιμοποιείται για δημιουργία σύνθετων περιγραμμάτων: καμπύλες Bezier (quadTo, cubicTo), τόξα (arcTo), γραμμές (lineTo). Το Path μπορεί να είναι κλειστό (close()) για γεμισμένα σχήματα ή ανοιχτό για γραμμές. Οι κύριες μέθοδοι drawPath() συνδυάζουν Path και Paint για την τελική σχεδίαση.

Βελτιστοποίηση σχεδίασης Canvas

Η απόδοση της σχεδίασης Canvas επηρεάζει άμεσα τα FPS της εφαρμογής. Κύρια προβλήματα: υπερβολικές δεσμεύσεις στο onDraw(), συχνές invalidate() και μη βέλτιστη χρήση της Επιτάχυνσης Υλικού.

Δημιουργήστε αντικείμενα εκτός onDraw()

Τα Paint, Path, Rect, RectF και άλλα αντικείμενα πρέπει να δημιουργούνται μία φορά στον αρχικοποιητή ή στη μέθοδο setup(). Κάθε δέσμευση στο onDraw() δημιουργεί φόρτο στον garbage collector, οδηγώντας σε μικρο-καθυστερήσεις. Εξαίρεση — static ή companion object για αμετάβλητα αντικείμενα.

Χρησιμοποιήστε clipRect() για περιορισμό περιοχής

Εάν μεγάλο μέρος του View είναι κρυμμένο εκτός ορατής περιοχής (π.χ. σε ScrollView), χρησιμοποιήστε canvas.clipRect() για περιορισμό της σχεδίασης. Η Επιτάχυνση Υλικού σε αυτή την περίπτωση βελτιστοποιεί περαιτέρω την αποκοπή αόρατων εικονοστοιχείων.

kotlin
override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)

    // Αποκοπή σε ορατή περιοχή
    canvas.save()
    canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)

    // Απόδοση μεγάλης σκηνής
    renderScene(canvas)
    canvas.restore()
}

Χρησιμοποιήστε View.setLayerType() με LAYER_TYPE_HARDWARE για View με σύνθετα γραφικά Canvas που ενημερώνονται σπάνια. Για συχνά ενημερωμένες κινούμενες εικόνες, χρησιμοποιήστε LAYER_TYPE_NONE για να αποφύγετε τη δαπανηρή ενημέρωση του επιπέδου υλικού. Κάντε προφίλ μέσω GPU Profile Rendering και Android Studio Profiler.

Συχνές Ερωτήσεις

Μπορεί να δημιουργηθεί Canvas χωρίς View;

Ναι, μπορείτε να δημιουργήσετε Canvas(Bitmap) — έναν κατασκευαστή που δέχεται Bitmap. Αυτό χρησιμοποιείται για offscreen-απόδοση: σχεδιάζετε στο Bitmap και στη συνέχεια το εμφανίζετε μέσω drawBitmap(). Το Canvas μπορεί επίσης να δημιουργηθεί από Surface (για SurfaceView) ή μέσω Picture.

Ποια είναι η διαφορά μεταξύ Canvas και SurfaceView;

Canvas — είναι API για σχεδίαση σε View στο νήμα UI. SurfaceView — είναι ένα ξεχωριστό Surface που μπορεί να ενημερώνεται από το νήμα παρασκηνίου μέσω του δικού του Canvas (lockCanvas() / unlockCanvasAndPost()). Το SurfaceView είναι προτιμότερο για παιχνίδια και βίντεο.

Γιατί το Canvas δεν σχεδιάζει μετά από μετασχηματισμό;

Η πιο συχνή αιτία είναι οι μη ισορροπημένες save() και restore(). Εάν μετά τον μετασχηματισμό (translate, rotate) δεν κληθεί η restore(), το Canvas παραμένει στο τροποποιημένο σύστημα συντεταγμένων και τα επόμενα στοιχεία σχεδιάζονται με μετατόπιση. Ελέγξτε τα ζεύγη save()/restore().

Πώς να σχεδιάσω κείμενο στο κέντρο του Canvas;

Χρησιμοποιήστε Paint.setTextAlign(Paint.Align.CENTER) για οριζόντια στοίχιση και Paint.getTextBounds() ή Paint.descent() / ascent() για κάθετη. Κεντράρισμα: canvas.drawText(text, centerX, centerY - (ascent + descent) / 2, paint).

Υποστηρίζει το Canvas κινούμενα σχέδια;

Το Canvas από μόνο του δεν δημιουργεί κινούμενα σχέδια — απλώς σχεδιάζει την τρέχουσα κατάσταση. Η κίνηση επιτυγχάνεται μέσω διαδοχικών κλήσεων invalidate()postInvalidateOnAnimation()), σχεδιάζοντας κάθε φορά ένα νέο καρέ στο onDraw(). Για ομαλές κινήσεις χρησιμοποιήστε ValueAnimator ή Choreographer για συγχρονισμό με Vsync.

Σύνοψη

  • Canvas — κεντρική κλάση 2D σχεδίασης στο Android, παρέχει μεθόδους draw* για σχεδίαση πρωτογόνων, κειμένου και εικόνων
  • Paint — καθορίζει το οπτικό στυλ (χρώμα, πάχος, γέμισμα, shader) δημιουργείται μία φορά και επαναχρησιμοποιείται
  • save() / restore() — διαχείριση στοίβας μετασχηματισμών, κάθε μετασχηματισμός πρέπει να είναι σε ζεύγος save/restore
  • Path — δημιουργία αυθαίρετων περιγραμμάτων και καμπύλων Bezier για σύνθετα διανυσματικά γραφικά
  • Offscreen Bitmap — τεχνική προσωρινής αποθήκευσης σύνθετων σκηνών μέσω Canvas(Bitmap) για μείωση φόρτου onDraw()
  • Επιτάχυνση Υλικού — επιτάχυνση GPU για Canvas από Android 3.0, επιβάλλει περιορισμούς σε ορισμένες λειτουργίες (clipPath)
  • Προφίλ — GPU Profile Rendering και Android Studio Profiler είναι υποχρεωτικά για εύρεση σημείων συμφόρησης στο onDraw()

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

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

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

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