onMeasure(): Was es ist, MeasureSpec-Modi und Methodenüberschreibung

Autor: IT Sectr Veröffentlicht: 2026-07-22 Lesezeit: 9 Min.

onMeasure() ist eine protected-Methode der Klasse android.view.View, die vom Android-System aufgerufen wird, um die Größe einer View zu bestimmen. Das System übergibt zwei MeasureSpec-Objekte an die Methode, die jeweils einen Messmodus (EXACTLY, AT_MOST oder UNSPECIFIED) und eine vom Eltern-Container vorgeschlagene Größe enthalten. Laut Android Developers Documentation (2026) ist das Überschreiben von onMeasure mit korrekter MeasureSpec-Behandlung ein obligatorischer Schritt für alle benutzerdefinierten Views und ViewGroups, die eine genaue Größenkontrolle erfordern.

Wichtigste Erkenntnisse

  • onMeasure(int widthMeasureSpec, int heightMeasureSpec) — die View-Methode zum Messen von Größen mit MeasureSpec vom Eltern-Element
  • MeasureSpec — ein 32-Bit-Wert, der den Messmodus (UNSPECIFIED, EXACTLY, AT_MOST) und die Größe codiert
  • setMeasuredDimension(int w, int h) — ein obligatorischer Aufruf innerhalb von onMeasure, der die endgültigen View-Abmessungen festlegt
  • Zwei-Durchlauf-Algorithmus zur Messung: Das Eltern-Element misst Kinder, dann melden Kinder ihre Größen, und das Eltern-Element trifft die endgültige Entscheidung
  • measureChildWithMargins — eine Hilfsmethode zum Messen von Child-Views in benutzerdefinierten ViewGroups

Was ist onMeasure()?

onMeasure(int widthMeasureSpec, int heightMeasureSpec) ist eine Methode der Klasse View, die das Android-System aufruft, um die Breite und Höhe einer Ansicht zu bestimmen. Der Entwickler überschreibt diese Methode, um anzugeben, welche Größe die View basierend auf den in MeasureSpec übergebenen Einschränkungen haben soll. Ohne korrektes Überschreiben von onMeasure kann eine benutzerdefinierte View falsch angezeigt werden oder gar nicht erscheinen.

Das System ruft onMeasure während der measure-Phase des View-Lebenszyklus auf, die den Phasen layout (onLayout) und draw (onDraw) vorausgeht. Wenn eine View onMeasure nicht überschreibt, wird die Implementierung der Superklasse verwendet, die Standardgrößen basierend auf background drawable oder layout_params festlegt. Der Aufruf von super.onMeasure(widthMeasureSpec, heightMeasureSpec) funktioniert nur für Standard-Unterklassen von View wie TextView oder ImageView.

Eine wichtige Anforderung an onMeasure ist, dass der Aufruf von setMeasuredDimension(int, int) am Ende der Methode vorhanden sein muss. Fehlt dieser Aufruf, löst das System eine IllegalStateException aus, die besagt, dass die View keine gemessenen Abmessungen festgelegt hat. Die endgültigen Abmessungen sind nach Abschluss der measure-Phase über die Getter getMeasuredWidth() und getMeasuredHeight() verfügbar.

MeasureSpec-Modi: Drei Schlüsselwerte

MeasureSpec ist eine 32-Bit-Ganzzahl, bei der die oberen 2 Bits den Messmodus und die unteren 30 Bits die Größe codieren. Der Modus bestimmt, wie frei die View bei der Wahl ihrer eigenen Größe ist. Android bietet drei Modi: EXACTLY, AT_MOST und UNSPECIFIED. Jeder Modus gibt eine andere Verarbeitungslogik in onMeasure vor.

MeasureSpec-ModusWertVerhalten
EXACTLYEltern-Element hat genaue Größe angegebenDie View muss genau in die angegebene Größe passen, wenn sie Grenzen nicht überschreiten möchte
AT_MOSTEltern-Element hat Maximalgröße festgelegtDie View kann jede Größe von 0 bis zum angegebenen Maximum wählen
UNSPECIFIEDEltern-Element erzwingt keine EinschränkungenDie View kann jede gewünschte Größe ohne obere Grenze wählen

Zum Extrahieren von Modus und Größe aus MeasureSpec werden die statischen Methoden der Klasse MeasureSpec verwendet: MeasureSpec.getMode(int) gibt einen der drei Modi zurück (EXACTLY, AT_MOST, UNSPECIFIED), und MeasureSpec.getSize(int) gibt die numerische Größe in Pixeln zurück. Zum Erstellen eines benutzerdefinierten MeasureSpec wird MeasureSpec.makeMeasureSpec(int size, int mode) verwendet. Diese drei Methoden decken alle Szenarien der Arbeit mit Größen in onMeasure ab.

Typische MeasureSpec-Verarbeitungslogik

Das Standardmuster zur MeasureSpec-Behandlung: Wenn der Modus EXACTLY ist, verwenden Sie die übergebene Größe als endgültig; wenn AT_MOST, wählen Sie das Minimum aus gewünschter Größe (View-Inhalt) und übergebenem Maximum; wenn UNSPECIFIED, verwenden Sie die gewünschte View-Größe ohne Einschränkungen. Dieses Muster gewährleistet korrektes Verhalten unter beliebigen Eltern-Einschränkungen.

kotlin
override fun onMeasure(widthMeasureSpec: Int,
                       heightMeasureSpec: Int) {
    val desiredWidth = 200
    val desiredHeight = 100

    val widthMode = MeasureSpec.getMode(widthMeasureSpec)
    val widthSize = MeasureSpec.getSize(widthMeasureSpec)
    val heightMode = MeasureSpec.getMode(heightMeasureSpec)
    val heightSize = MeasureSpec.getSize(heightMeasureSpec)

    val width = when (widthMode) {
        MeasureSpec.EXACTLY -> widthSize
        MeasureSpec.AT_MOST -> minOf(desiredWidth, widthSize)
        else -> desiredWidth
    }
    val height = when (heightMode) {
        MeasureSpec.EXACTLY -> heightSize
        MeasureSpec.AT_MOST -> minOf(desiredHeight, heightSize)
        else -> desiredHeight
    }
    setMeasuredDimension(width, height)
}

Verwendung von resolveSize

Zur Vereinfachung der Standardlogik stellt Android die Methode resolveSizeAndState bereit, die die gewünschte Größe und MeasureSpec nimmt und die endgültige Größe mit dem korrekten Modus zurückgibt. Diese Methode implementiert das oben beschriebene Muster in einer einzigen Codezeile. Die Funktion resolveSize(int size, int measureSpec) ist ebenfalls verfügbar und gibt eine saubere Größe ohne Statusbits zurück.

Zwei-Durchlauf-Messalgorithmus

Android verwendet einen Zwei-Durchlauf-Messalgorithmus, der sicherstellt, dass jede View in der Hierarchie korrekte Abmessungen unter Berücksichtigung von Eltern-Einschränkungen und Kind-Präferenzen erhält. Im ersten Durchlauf übergibt das Eltern-Element MeasureSpec mit Einschränkungen an Child-Views, und die Child-Views berechnen ihre gewünschten Größen. Im zweiten Durchlauf trifft das Eltern-Element die endgültige Größenentscheidung.

Für ViewGroup ist der Messprozess komplexer: Das Eltern-Element muss zunächst alle seine Kinder messen und dann seine eigene Größe basierend auf deren Größen bestimmen. Der Aufruf von measureChildren(int widthMeasureSpec, int heightMeasureSpec) durchläuft alle Child-Views und ruft für jede measure(child, childWidthSpec, childHeightSpec) auf. Nach dem Messen aller Kinder ruft die ViewGroup setMeasuredDimension mit ihren eigenen Abmessungen auf.

Eine wichtige Nuance: Die measure-Methode (öffentlich, final) kann nicht überschrieben werden — stattdessen wird onMeasure überschrieben. Dadurch kann das System Wartungsaufgaben vor und nach onMeasure ausführen, wie das Überprüfen von Größenänderungen und das Berechnen des Dirty-Bereichs für die anschließende Zeichnung. Wenn eine View feste Abmessungen hat, ist das Überschreiben von onMeasure möglicherweise nicht erforderlich.

MEASURED_SIZE_STATE-Flag

MeasureSpec enthält nicht nur Größe und Modus, sondern auch Statusbits, die über MeasureSpec.getMode() zugänglich sind. Nach dem Aufruf von setMeasuredDimension wird der Status Teil der gemessenen Abmessungen der View und kann über getMeasuredState() überprüft werden. Dies wird in ScrollView und anderen scrollbaren Containern verwendet, um Einschränkungen korrekt an Kinder weiterzugeben.

Beispiel zum Überschreiben von onMeasure in Kotlin

Betrachten wir ein praktisches Beispiel zum Erstellen einer benutzerdefinierten View mit überschriebenem onMeasure für quadratische Anzeige. Die Klasse SquareView erweitert View und stellt sicher, dass Breite und Höhe unabhängig vom übergebenen MeasureSpec immer gleich sind. In onMeasure wird die minimale Seite bestimmt und die quadratische Größe festgelegt.

kotlin
class SquareView(context: Context)
    : View(context) {

    override fun onMeasure(widthMeasureSpec: Int,
                       heightMeasureSpec: Int) {
        val widthSize =
            MeasureSpec.getSize(widthMeasureSpec)
        val heightSize =
            MeasureSpec.getSize(heightMeasureSpec)
        val size = minOf(widthSize, heightSize)
        setMeasuredDimension(size, size)
    }
}

Benutzerdefinierte ViewGroup mit Kindmessung

ViewGroup erfordert eine komplexere onMeasure-Logik, da zunächst Kinder gemessen werden müssen, bevor die eigene Größe der ViewGroup bestimmt wird. Das CascadeLayout-Beispiel verteilt Kinder mit einem Versatz in Kaskadenform. Nach dem Messen aller Kinder über measureChildWithMargins werden die Gesamtbreite und -höhe berechnet.

kotlin
class CascadeLayout(context: Context)
    : ViewGroup(context) {

    private val cascadeOffset = 40

    override fun onMeasure(widthMeasureSpec: Int,
                       heightMeasureSpec: Int) {
        var maxWidth = 0
        var totalHeight = 0
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            measureChildWithMargins(child,
                widthMeasureSpec,
                cascadeOffset * i,
                heightMeasureSpec, 0)
            maxWidth = maxOf(maxWidth,
                child.measuredWidth +
                cascadeOffset * i)
            totalHeight += child.measuredHeight
        }
        setMeasuredDimension(
            resolveSize(maxWidth, widthMeasureSpec),
            resolveSize(totalHeight, heightMeasureSpec))
    }

    override fun generateLayoutParams(attrs: AttributeSet?)
        : LayoutParams = MarginLayoutParams(context, attrs)

    override fun onLayout(changed: Boolean,
                       l: Int, t: Int,
                       r: Int, b: Int) {
        var top = t
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            val left = l + cascadeOffset * i
            child.layout(left, top,
                left + child.measuredWidth,
                top + child.measuredHeight)
            top += child.measuredHeight
        }
    }
}

Häufige Fehler beim Überschreiben von onMeasure

Fehlender setMeasuredDimension-Aufruf ist der häufigste Fehler. Wenn ein Entwickler onMeasure überschreibt, aber setMeasuredDimension nicht aufruft, stürzt die Anwendung mit IllegalStateException ab. Dies passiert besonders häufig, wenn die Methode bedingte Verzweigungen enthält und in einem Zweig der Aufruf fehlt. Jeder Code-Zweig in onMeasure muss mit einem setMeasuredDimension-Aufruf enden.

Ignorieren des AT_MOST-Modus ist der zweithäufigste Fehler. Wenn eine View im AT_MOST-Modus immer die übergebene Größe verwendet, anstatt basierend auf dem Inhalt zu berechnen, kann der Eltern-Container den Platz nicht korrekt verteilen. Beispielsweise sollte ein TextView im AT_MOST-Modus die Textbreite berechnen und das Minimum aus gewünschter und übergebener Breite verwenden. Das Ignorieren von AT_MOST führt dazu, dass die View selbst bei kleinem Inhalt den gesamten verfügbaren Platz belegt.

Objekterstellung innerhalb von onMeasure ist ein klassischer Leistungsfehler. Da onMeasure mehrfach aufgerufen werden kann (bei jeder Layout-Anforderung), belastet das Erstellen von Objekten (Paint, Rect, String) innerhalb dieser Methode den Speicher und löst Garbage Collection aus. Alle Objekte sollten einmal im View-Konstruktor erstellt werden, und in onMeasure sollte nur die Größenberechnungslogik ausgeführt werden. Dieselbe Regel gilt für onDraw und onLayout.

Messen von Child-Views in ViewGroup

measureChildWithMargins ist eine geschützte ViewGroup-Methode, die eine einzelne Child-View unter Berücksichtigung ihrer MarginLayoutParams misst. Die Methode akzeptiert den MeasureSpec des Eltern-Elements und akkumulierte Breiten- und Höhenversätze. Sie passt den MeasureSpec für die Child-View automatisch an, indem sie Parent-Paddings und Child-Margins subtrahiert, und übergibt den angepassten MeasureSpec an child.measure().

Für fortgeschrittene Messlogik kann eine ViewGroup measureChild(View child, int parentWidthSpec, int parentHeightSpec) überschreiben oder direkt mit MeasureSpec für jedes Kind arbeiten. Beispielsweise iteriert LinearLayout in onMeasure über alle Child-Views, misst jede unter Berücksichtigung ihres layout_weight und verteilt den verbleibenden Raum proportional. Dieser Ansatz ermöglicht die Implementierung beliebiger Layout-Algorithmen.

Das Zwischenspeichern von Messergebnissen über den Measure-Cache-Mechanismus ist über das Flag setMeasureWithLargestChildEnabled in bestimmten ViewGroups verfügbar. In den meisten Fällen wird onMeasure jedoch bei jeder Layout-Änderung erneut aufgerufen, und Caching kommt nicht zur Anwendung. In benutzerdefinierten ViewGroups wird empfohlen, Berechnungen in onMeasure zu minimieren, anstatt sich auf Caching zu verlassen.

Häufig gestellte Fragen

Muss onMeasure für eine benutzerdefinierte View überschrieben werden?

Ja, wenn die benutzerdefinierte View direkt von der View-Klasse erbt. Wenn sie von TextView, ImageView oder Button mit deren Standardgrößen erbt, kann onMeasure unverändert bleiben. Für ViewGroup ist das Überschreiben von onMeasure immer erforderlich — andernfalls werden Kinder nicht korrekt gemessen.

Was passiert, wenn setMeasuredDimension nicht aufgerufen wird?

Das Android-System löst IllegalStateException mit der Meldung „The View did not call setMeasuredDimension“ aus. Diese Ausnahme tritt in der measure()-Methode nach Abschluss von onMeasure auf, wenn die endgültigen Abmessungen null geblieben sind. Die Ausnahme führt zum Absturz der Anwendung, wenn sie nicht über try-catch behandelt wird.

Was ist der Unterschied zwischen getWidth und getMeasuredWidth?

getMeasuredWidth() gibt die in onMeasure (Messphase) festgelegte Größe zurück. getWidth() gibt die tatsächliche Größe zurück, die die View in onLayout nach allen Positionsanpassungen erhalten hat. Bei den meisten Views stimmen diese Werte überein, aber in benutzerdefinierten ViewGroups können sie abweichen.

Kann man Animationen oder den View-Status innerhalb von onMeasure ändern?

Nein, onMeasure ist ausschließlich für die Größenberechnung vorgesehen. Das Ändern des Status, Starten von Animationen, Netzwerkaktivitäten oder Aktualisieren von Daten in dieser Methode verstößt gegen die Android-Architektur und kann zu rekursiven measure-Aufrufen führen, da Statusänderungen requestLayout auslösen können.

Wie interagiert onMeasure mit ConstraintLayout?

ConstraintLayout verwaltet die Kindmessung unabhängig basierend auf definierten Einschränkungen. Wenn eine benutzerdefinierte View innerhalb von ConstraintLayout onMeasure überschreibt, muss sie den von ConstraintLayout übergebenen MeasureSpec korrekt verarbeiten, andernfalls können Einschränkungen unwirksam sein. ConstraintLayout verwendet einen Zwei-Durchlauf-Algorithmus mit einem eigenen WidgetContainer zur Berechnung.

Zusammenfassung

  • onMeasure() — die View-Methode zur Bestimmung von Abmessungen, aufgerufen vom Android-System während der measure-Phase
  • MeasureSpec codiert den Messmodus (EXACTLY, AT_MOST, UNSPECIFIED) und die vom Eltern-Element übergebene Größe
  • setMeasuredDimension — ein obligatorischer Aufruf am Ende von onMeasure, der die endgültigen Abmessungen festlegt
  • resolveSize — eine Hilfsmethode, die die Standard-MeasureSpec-Behandlungslogik in einer Zeile implementiert
  • Zwei-Durchlauf-Algorithmus gewährleistet korrekte Messung in der Eltern-Kind-Hierarchie
  • measureChildWithMargins wird zum Messen von Child-Views in benutzerdefinierten ViewGroups mit Abständen verwendet
  • Das Erstellen von Objekten innerhalb von onMeasure wird aufgrund des GC-Risikos und von Frame-Einbrüchen dringend vermieden

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch