Android Academy · Les

Aangepaste Views

Teken aangepaste UI-componenten vanaf nul. Breid View uit, implementeer onMeasure en onDraw met Canvas en Paint, definieer aangepaste XML-attributen en bouw samengestelde views.

Les 3 van 513 stappen

Aangepaste Views is een gratis Android Academy-les op CoddyKit. Dit is les 3 van 5. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Android Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Android Academy bevat in totaal 5 lessen.

Waarom aangepaste views?

Soms doen de ingebouwde Android-views niet precies wat je nodig hebt. Met aangepaste views kun je:

  • Vormen, grafieken, voortgangsringen of diagrammen tekenen die niet in de SDK bestaan
  • Merkgebonden UI-componenten maken die overal in de app consistent worden gebruikt
  • Meerdere views combineren tot één herbruikbare component (Compound View)
  • Betere prestaties bereiken door geneste layouthiërarchieën te vermijden

View uitbreiden

Maak een aangepaste view door View uit te breiden, of een subklasse zoals ImageView. Overschrijf de vereiste constructor:

class CircleProgressView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    var progress: Float = 0f
        set(value) {
            field = value.coerceIn(0f, 100f)
            invalidate()   // trigger redraw
        }

    // onMeasure and onDraw go here
}

onMeasure()

onMeasure() vertelt de bovenliggende view hoe groot deze view wil zijn. Roep aan het einde altijd setMeasuredDimension() aan:

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val desiredSize = 200  // dp → pixels
    val px = (desiredSize * resources.displayMetrics.density).toInt()

    val width  = resolveSize(px, widthMeasureSpec)
    val height = resolveSize(px, heightMeasureSpec)

    // Square: same width and height
    val size = minOf(width, height)
    setMeasuredDimension(size, size)
}

Paint — het tekengereedschap

Een Paint-object bevat de stijlinformatie voor het tekenen, zoals kleur, lijndikte en antialiasing. Maak het één keer aan — nooit binnen onDraw():

class CircleProgressView ... : View(...) {

    // Create Paint in init, not in onDraw!
    private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.LTGRAY
        style = Paint.Style.STROKE
        strokeWidth = 20f
        strokeCap = Paint.Cap.ROUND
    }

    private val progressPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.parseColor("#6750A4")
        style = Paint.Style.STROKE
        strokeWidth = 20f
        strokeCap = Paint.Cap.ROUND
    }
}

onDraw() — de view tekenen

onDraw(canvas) wordt elke keer aangeroepen wanneer de view opnieuw moet worden getekend. Gebruik het Canvas om vormen, tekst en bitmaps te tekenen:

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

    val cx = width / 2f
    val cy = height / 2f
    val radius = (minOf(width, height) / 2f) - 30f

    // Draw background circle
    canvas.drawCircle(cx, cy, radius, backgroundPaint)

    // Draw progress arc
    val oval = RectF(cx - radius, cy - radius, cx + radius, cy + radius)
    val sweepAngle = 360f * (progress / 100f)
    canvas.drawArc(oval, -90f, sweepAngle, false, progressPaint)
}

invalidate() versus requestLayout()

Twee methoden om een update te starten:

  • invalidate() — tekent de view opnieuw (roept onDraw aan). Gebruik dit wanneer de inhoud verandert maar het formaat gelijk blijft.
  • requestLayout() — meet opnieuw en tekent opnieuw (roept eerst onMeasure en daarna onDraw aan). Gebruik dit wanneer het formaat van de view verandert.

Aangepaste attributen (attrs.xml)

Declareer aangepaste XML-attributen, zodat de view vanuit layoutbestanden kan worden geconfigureerd:

<!-- res/values/attrs.xml -->
<resources>
    <declare-styleable name="CircleProgressView">
        <attr name="progressColor" format="color" />
        <attr name="trackColor"    format="color" />
        <attr name="strokeWidth"   format="dimension" />
        <attr name="progress"      format="float" />
    </declare-styleable>
</resources>

Aangepaste attributen lezen

Lees attrs in de constructor met obtainStyledAttributes:

init {
    context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView).use { ta ->
        progressPaint.color = ta.getColor(
            R.styleable.CircleProgressView_progressColor,
            Color.parseColor("#6750A4")
        )
        backgroundPaint.color = ta.getColor(
            R.styleable.CircleProgressView_trackColor,
            Color.LTGRAY
        )
        val sw = ta.getDimension(R.styleable.CircleProgressView_strokeWidth, 20f)
        progressPaint.strokeWidth = sw
        backgroundPaint.strokeWidth = sw
        progress = ta.getFloat(R.styleable.CircleProgressView_progress, 0f)
    }
}

De aangepaste view in XML gebruiken

Gebruik je aangepaste view in layout-XML met het volledige klassepad en aangepaste attributen:

<!-- In any layout XML -->
<com.example.myapp.CircleProgressView
    android:id="@+id/progressView"
    android:layout_width="120dp"
    android:layout_height="120dp"
    app:progress="65"
    app:progressColor="@color/primary"
    app:trackColor="@color/surface_variant"
    app:strokeWidth="12dp" />

<!-- Control in code: -->
binding.progressView.progress = 75f

Samengestelde views

Een samengestelde view combineert bestaande views tot één herbruikbare component. Breid een layoutklasse zoals LinearLayout uit:

class SearchBarView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {

    private val binding = ViewSearchBarBinding.inflate(LayoutInflater.from(context), this)

    init {
        orientation = HORIZONTAL
        binding.ivSearch.setOnClickListener {
            onSearchClick?.invoke(binding.etSearch.text.toString())
        }
    }

    var onSearchClick: ((String) -> Unit)? = null

    fun setHint(hint: String) { binding.etSearch.hint = hint }
}

Tekst tekenen

Teken tekst op een Canvas met drawText(). Centreer de tekst nauwkeurig met Paint.getFontMetrics():

private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.BLACK
    textSize = 48f
    textAlign = Paint.Align.CENTER
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val cx = width / 2f
    val cy = height / 2f

    // Vertically center the text:
    val fm = textPaint.fontMetrics
    val textY = cy - (fm.ascent + fm.descent) / 2f
    canvas.drawText("${progress.toInt()}%", cx, textY, textPaint)
}

Korte controle

Welke methode moet je aanroepen om je aangepaste view opnieuw te laten tekenen wanneer de gegevens veranderen maar het formaat gelijk blijft?

Samenvatting: aangepaste views

Je kunt nu alles op het scherm tekenen:

  • Breid View uit met @JvmOverloads constructor
  • onMeasure() — rapporteer het gewenste formaat met setMeasuredDimension()
  • Paint — definieer de stijl; maak het één keer aan, niet binnen onDraw()
  • onDraw(canvas) — teken cirkels, bogen, tekst en bitmaps
  • invalidate() om opnieuw te tekenen, requestLayout() om opnieuw te meten
  • Aangepaste attributen via attrs.xml voor XML-configuratie
  • Samengestelde view — breid een layout uit om bestaande views te combineren

Volgende: breng je UI tot leven met animaties en overgangen.

Gratis beginnen

Leer Kotlin met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
36
Lessen
152

Veelgestelde vragen

Is de les “Aangepaste Views” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Android Academy, waaronder “Aangepaste Views”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Android Academy bevat in totaal 5 lessen.

Wat leer ik in “Aangepaste Views”?

Teken aangepaste UI-componenten vanaf nul. Breid View uit, implementeer onMeasure en onDraw met Canvas en Paint, definieer aangepaste XML-attributen en bouw samengestelde views. Je oefent met Android Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Android Academy te beginnen?

Ervaring vooraf is niet nodig. Android Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 5.

Hoe lang duurt de les “Aangepaste Views”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Android Academy?

Ja. Elke les over Android Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Basisprincipes van Material Design
  2. Thema's en stijlen
  3. Aangepaste Views
  4. Animaties en transities
  5. Bottom Navigation en tabbladen
← Terug naar Android Academy