Canvas in Android: wat is het, Canvas-klasse en draw-methoden

Auteur: IT Sectr Gepubliceerd: 2026-07-21 Leestijd: 7 min

Canvas in Android — is een klasse uit het android.graphics-pakket die een API biedt voor 2D-tekening op View. Canvas werkt als een canvas waarop de ontwikkelaar geometrische figuren, tekst, afbeeldingen en paden tekent met behulp van verschillende draw*-methoden. Volgens Android Developers Documentation (2025) is Canvas het belangrijkste hulpmiddel voor aangepast tekenen in Android en wordt het samen met de Paint-klasse gebruikt voor het instellen van stijlen en kleuren. Elke aanroep van onDraw() ontvangt een kant-en-klare Canvas-instantie die is gekoppeld aan de bitmapbuffer van de view.

Belangrijkste punten

  • Canvas — klasse voor 2D-tekening in Android, biedt methoden drawRect, drawCircle, drawText, drawBitmap en andere
  • Paint — klasse die de tekenstijl bepaalt: kleur, dikte, vulling, effecten (schaduw, verloop)
  • onDraw(Canvas) — View-methode waarin al het tekenen via de ontvangen Canvas plaatsvindt
  • Canvas.save() en restore() — beheer van de transformatiestapel voor geneste coördinatensysteemtransformaties
  • Path — klasse voor het bouwen van willekeurige contouren en curven, doorgegeven aan drawPath(Path, Paint)

Wat is Canvas in Android

Canvas — is de centrale 2D-grafieklasse in Android die methoden biedt voor tekenen op een oppervlak. Elke Canvas is gekoppeld aan een Bitmap — een geheugengebied waarin de resultaten van tekenbewerkingen worden geschreven. Wanneer een View opnieuw wordt getekend, geeft het systeem een Canvas door aan onDraw() dat al is gekoppeld aan de buffer van deze View.

Canvas werkt in een coördinatensysteem waarbij (0,0) de linkerbovenhoek is, de X-as naar rechts gaat en de Y-as naar beneden. Alle tekenbewerkingen gebruiken de huidige status van Canvas, inclusief de transformatiematrix, het clipgebied (clip) en de Paint-stijl. Volgens Android Documentation (2025) omvat de Canvas API meer dan 30 draw*-methoden voor verschillende soorten grafische primitieven.

Canvas en Hardware Acceleratie

Sinds Android 3.0 (API 11) ondersteunt Canvas hardwareversnelling via DisplayList. In de versnelde modus worden Canvas-bewerkingen naar DisplayList geschreven en vervolgens op de GPU uitgevoerd. Dit geeft een aanzienlijke prestatieverbetering, maar legt beperkingen op: sommige Canvas-bewerkingen (clipPath met niet-Path-clip) worden niet ondersteund in de versnelde modus.

Belangrijkste Canvas-methoden voor tekenen

Canvas biedt een reeks methoden voor het tekenen van basisprimitieven. Elke methode ontvangt geometrische parameters en een Paint-object dat de visuele stijl bepaalt.

MethodeDoelVoorbeeld
drawRect()Rechthoek tekenencanvas.drawRect(10f, 10f, 100f, 100f, paint)
drawCircle()Cirkel tekenencanvas.drawCircle(50f, 50f, 30f, paint)
drawLine()Lijn tekenencanvas.drawLine(0f, 0f, 100f, 100f, paint)
drawText()Tekst tekenencanvas.drawText("Hello", 10f, 20f, paint)
drawBitmap()Afbeelding tekenencanvas.drawBitmap(bitmap, 0f, 0f, paint)
drawPath()Willekeurig pad tekenencanvas.drawPath(path, paint)
drawOval()Ovaal tekenencanvas.drawOval(rectF, paint)
drawArc()Boog of sector tekenencanvas.drawArc(rectF, 0f, 90f, true, paint)

Elke methode kan in willekeurige volgorde worden aangeroepen — Canvas tekent in de volgorde van aanroepen, waarbij nieuwe elementen over vorige worden geplaatst. Voor complexe composities wordt de techniek van meerlaags tekenen met opslaan en herstellen van de Canvas-status gebruikt.

Paint-klasse: configuratie van stijlen en effecten

Paint — is de klasse die bepaalt hoe Canvas zal tekenen. Zonder Paint zijn Canvas-methoden nutteloos — het stelt kleur, lijndikte, vulstijl, tekstgrootte, effecten (schaduw, verloop, vervaging) en overvloeimodus in.

Paint heeft belangrijke eigenschappen: color (kleur), style (FILL, STROKE of FILL_AND_STROKE), strokeWidth (lijndikte), textSize (tekstgrootte), isAntiAlias (anti-aliasing), shader (verloop of afbeelding). Het maken van een Paint-object is een dure bewerking, dus moet het eenmaal worden gemaakt en hergebruikt.

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

In dit voorbeeld worden twee Paint-objecten gebruikt: één voor het vullen van de cirkel met paars, de tweede voor de witte omtrek. De scheiding in fill en stroke is een standaardpraktijk die flexibel beheer van het uiterlijk mogelijk maakt zonder objecten opnieuw te maken.

Shader en verlopen

Voor verloopvullingen accepteert Paint een Shader — subklassen LinearGradient, RadialGradient, SweepGradient. Shader wordt aan Paint gekoppeld via de methode setShader() en bepaalt hoe de kleur verandert over het tekengebied.

Canvas-transformaties: translate, rotate, scale

Canvas ondersteunt matrixtransformaties van het coördinatensysteem: translate() (verplaatsing), rotate() (rotatie), scale() (schaling) en skew() (scheeftrekken). Transformaties stapelen zich op: elke volgende aanroep wordt bovenop vorige toegepast.

Beheer van de transformatiestapel gebeurt via save() en restore(). save() slaat de huidige Canvas-status (matrix, clip) op in de stapel, restore() herstelt de laatst opgeslagen status. Tussen save() en restore() kunnen geneste transformaties voorkomen.

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

    canvas.save() // Bewaar begintoestand
    canvas.translate(100f, 100f) // Verplaats oorsprong

    // Eerste vierkant
    canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)

    canvas.save() // Bewaar na verplaatsing
    canvas.rotate(45f, 25f, 25f) // Roteer rond midden vierkant

    // Geroteerd vierkant
    canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
    canvas.restore() // Herstel na rotatie

    canvas.restore() // Herstel begintoestand
}

Gebruik altijd save() vóór het begin van transformaties en restore() na voltooiing. Ongebalanceerde save/restore leiden tot ophoping van de matrix en incorrect tekenen van volgende elementen.

Canvas met Bitmap en Path voor complexe graphics

Voor complexe graphics wordt Canvas gecombineerd met Bitmap en Path. Bitmap wordt gebruikt voor het laden van afbeeldingen en het cachen van gerenderde frames. Path — voor het bouwen van willekeurige Bezier-curven, veelhoeken en complexe contouren.

Offscreen Bitmap-buffer

Techniek van offscreen-rendering: er wordt een Bitmap gemaakt, waarop een complexe scène wordt getekend via een aparte Canvas, en vervolgens wordt de voltooide Bitmap weergegeven in onDraw() via drawBitmap(). Dit maakt het mogelijk complexe graphics bij te werken zonder elke frame volledig opnieuw te tekenen.

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)

    // Render scène eenmalig
    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 wordt gebruikt voor het bouwen van complexe contouren: Bezier-curven (quadTo, cubicTo), bogen (arcTo), lijnen (lineTo). Path kan gesloten zijn (close()) voor gevulde vormen of open voor lijnen. De belangrijkste methoden drawPath() combineren Path en Paint voor het uiteindelijke tekenen.

Optimalisatie van Canvas-tekening

De prestaties van Canvas-tekening beïnvloeden direct de FPS van de applicatie. Belangrijkste problemen: overmatige allocaties in onDraw(), frequente invalidate() en suboptimaal gebruik van Hardware Acceleratie.

Maak objecten buiten onDraw()

Paint, Path, Rect, RectF en andere objecten moeten eenmalig worden gemaakt in de initialisator of setup()-methode. Elke allocatie in onDraw() belast de garbage collector, wat leidt tot micro-hapers. Uitzondering — static of companion object voor immutable objecten.

Gebruik clipRect() voor het beperken van het gebied

Als een groot deel van de View verborgen is buiten het zichtbare gebied (bijv. in ScrollView), gebruik dan canvas.clipRect() om het tekenen te beperken. Hardware Acceleratie optimaliseert in dit geval extra het wegsnijden van onzichtbare pixels.

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

    // Knip naar zichtbaar gebied
    canvas.save()
    canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)

    // Render grote scène
    renderScene(canvas)
    canvas.restore()
}

Gebruik View.setLayerType() met LAYER_TYPE_HARDWARE voor View met complexe Canvas-graphics die zelden wordt bijgewerkt. Voor vaak bijgewerkte animaties gebruik je LAYER_TYPE_NONE om dure updates van de hardwarelaag te voorkomen. Profileer via GPU Profile Rendering en Android Studio Profiler.

Veelgestelde vragen

Kan Canvas zonder View worden gemaakt?

Ja, je kunt Canvas(Bitmap) maken — een constructor die Bitmap accepteert. Dit wordt gebruikt voor offscreen-rendering: je tekent op Bitmap en geeft het vervolgens weer via drawBitmap(). Canvas kan ook worden gemaakt van Surface (voor SurfaceView) of via Picture.

Wat is het verschil tussen Canvas en SurfaceView?

Canvas — is een API voor tekenen op View in de UI-thread. SurfaceView — is een aparte Surface die kan worden bijgewerkt vanuit de achtergrondthread via zijn eigen Canvas (lockCanvas() / unlockCanvasAndPost()). SurfaceView heeft de voorkeur voor games en video.

Waarom tekent Canvas niet na transformatie?

De meest voorkomende oorzaak zijn ongebalanceerde save() en restore(). Als na transformatie (translate, rotate) geen restore() wordt aangeroepen, blijft Canvas in het gewijzigde coördinatensysteem en worden volgende elementen met verschuiving getekend. Controleer de save()/restore()-paren.

Hoe teken ik tekst in het midden van Canvas?

Gebruik Paint.setTextAlign(Paint.Align.CENTER) voor horizontale uitlijning en Paint.getTextBounds() of Paint.descent() / ascent() voor verticaal. Centrering: canvas.drawText(text, centerX, centerY - (ascent + descent) / 2, paint).

Ondersteunt Canvas animatie?

Canvas zelf animeert niet — het tekent alleen de huidige status. Animaties worden bereikt door opeenvolgende aanroepen van invalidate() (of postInvalidateOnAnimation()), waarbij elke keer een nieuw frame wordt getekend in onDraw(). Voor soepele animaties gebruik je ValueAnimator of Choreographer voor synchronisatie met Vsync.

Samenvatting

  • Canvas — centrale 2D-tekenklasse in Android, biedt draw*-methoden voor het tekenen van primitieven, tekst en afbeeldingen
  • Paint — bepaalt de visuele stijl (kleur, dikte, vulling, shaders); eenmaal gemaakt en hergebruikt
  • save() / restore() — beheer van de transformatiestapel; elke transformatie moet in een save/restore-paar zijn
  • Path — bouwen van willekeurige contouren en Bezier-curven voor complexe vector graphics
  • Offscreen Bitmap — techniek voor het cachen van complexe scènes via Canvas(Bitmap) om de belasting van onDraw() te verminderen
  • Hardware Acceleratie — GPU-versnelling voor Canvas sinds Android 3.0, legt beperkingen op aan sommige bewerkingen (clipPath)
  • Profilering — GPU Profile Rendering en Android Studio Profiler zijn verplicht voor het vinden van knelpunten in onDraw()

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook