Aufschlüsselung der Modifikatoren nach Phase

In Jetpack Compose werden Modifikatoren in verschiedenen Phasen ausgeführt. Die folgende Aufschlüsselung zeigt, zu welcher Phase gängige Modifizierer gehören und wann ihre Argumente oder Lambdas ausgewertet werden.

Phase 1: Kompositionsphase

Mit diesen Modifikatoren werden Argumente synchron im @Composable-Body ausgewertet. Jeder hier gelesene Zustand registriert eine Abhängigkeit vom Bereich für den Neustart der komponierbaren Funktion und löst bei Änderung eine vollständige Neukomposition aus.

  • Statische Dimensions- und Größenanpassungsmodifizierer:
    • Modifier.size(dp), Modifier.width(dp), Modifier.height(dp)
    • Modifier.fillMaxSize(), Modifier.fillMaxWidth(), Modifier.fillMaxHeight()
    • Modifier.wrapContentSize(), Modifier.wrapContentWidth(), Modifier.wrapContentHeight()
    • Modifier.requiredSize(), Modifier.defaultMinSize()
    • Modifier.aspectRatio(ratio)
    • Modifier.weight(weight) (in RowScope oder ColumnScope)
    • Modifier.width(IntrinsicSize.Min / Max)
    • Modifier.height(IntrinsicSize.Min / Max)
  • Statischer Abstand und Insets:
    • Modifier.padding(all = dp), Modifier.padding(start, top, end, bottom)
    • Modifier.windowInsetsPadding(insets), Modifier.statusBarsPadding()
  • Visuelle Modifikatoren für Direktwerte:
    • Modifier.alpha(float) (liest den Status während der Komposition)
    • Modifier.rotate(degrees) (liest den Status während der Komposition)
    • Modifier.scale(scaleX, scaleY) (liest den Status während der Komposition)
    • Modifier.background(color = Color, shape = Shape)
    • Modifier.border(width, color, shape)
    • Modifier.shadow(elevation, shape)
    • Modifier.clip(shape)
    • Modifier.blur(radius)
  • Modifizierer für statische Positionen:
    • Modifier.offset(x = dp, y = dp) (direct value overload)
    • Modifier.absoluteOffset(x = dp, y = dp)
  • Dynamische zusammensetzbare Modifizierer:
    • Modifier.composed { ... } (führt den Factory-Body während der Komposition aus)

Phase 2: Layoutphase

Die Layoutphase ist in zwei separate Teilschritte mit separaten Invalidierungsbereichen unterteilt:

Schritt 2A: Messung

Bestimmt die Größe (width, height) und die Einschränkungen. Wenn hier ein Status gelesen wird, wird eine erneute Analyse und Platzierung ausgelöst:

  • Modifier.layout { measurable, constraints -> ... }: Code vor layout(w, h) wird während der Messung ausgeführt.

Schritt 2B: Callbacks für Platzierung und Layout

Bestimmt die Koordinatenposition (x, y). Der hier gelesene Status löst nur das erneute Platzieren aus (Messung und Zusammensetzung werden übersprungen):

  • Modifier.offset { IntOffset(x, y) } (Lambda-Überlastung)
  • Modifier.absoluteOffset { IntOffset(x, y) } (Lambda-Überlastung)
  • Modifier.layout { ... layout(w, h) { placeable.place(x, y) } }: Code im layout(w, h) { ... }-Block.
  • Modifier.onPlaced { layoutCoordinates -> ... }: Wird aufgerufen, nachdem die übergeordneten Koordinaten während der Platzierung ermittelt wurden.
  • Modifier.onSizeChanged { intSize -> ... }: Wird nach Abschluss der Layoutmessung aufgerufen, wenn sich die Größe geändert hat.
  • Modifier.onGloballyPositioned { layoutCoordinates -> ... }: Wird aufgerufen, nachdem der gesamte Layoutdurchlauf des Fensters abgeschlossen ist.

Phase 3: Ziehungsphase

Diese Modifikatoren werden während des Zeichnens des Canvas ausgeführt. Wenn der Status in diesen Blöcken gelesen wird, werden sowohl die Komposition als auch das Layout übersprungen und nur der Zeichenvorgang wird ausgeführt:

  • Modifier.graphicsLayer { ... }:
    • In der Lambda-Funktion aktualisierte Attribute: alpha, translationX, translationY, scaleX, scaleY, rotationX, rotationY, rotationZ, shadowElevation, shape, clip, renderEffect, transformOrigin.
  • Modifier.drawBehind { ... }:
    • Zeichnet Canvas-Befehle hinter den zusammensetzbaren Inhalten.
  • Modifier.drawWithContent { ... }:
    • Steuert die Zeichenreihenfolge mit drawContent().
  • Modifier.drawWithCache { ... }:
    • Der äußere Block wird bei Größen- oder Layoutänderungen ausgeführt, um Path-, Paint- oder Brush-Objekte im Cache zu speichern. onDrawBehind oder onDrawWithContent wird bei jedem Rendern eines Frames ausgeführt.

Außerhalb des Recomposition-Loops – Beobachtungsmodifikatoren

Einige Modifikatoren werden außerhalb der drei Frame-Phasen ausgeführt, um Barrierefreiheit, Nutzereingaben und Lebenszyklusbeobachtungen zu verarbeiten.

Semantik und Bedienungshilfen

Verarbeitet semantische Eigenschaften für Bedienungshilfen (TalkBack) und Tests:

  • Modifier.semantics { ... }
  • Modifier.clearAndSetSemantics { ... }

Eingabe, Gesten und Ereignisse

Wird außerhalb der dreiphasigen Frame-Rendering-Pipeline ausgeführt und empfängt OS-Bewegungsereignisse und Nutzerinteraktionen:

  • Modifier.pointerInput(key) { detectTapGestures { ... } } / detectDragGestures / awaitPointerEventScope
  • Modifier.clickable(enabled, onClickLabel) { ... }
  • Modifier.combinedClickable { ... }
  • Modifier.toggleable { ... }
  • Modifier.selectable { ... }
  • Modifier.draggable(...) / Modifier.scrollable(...) / Modifier.draggable2D(...)
  • Modifier.onFocusChanged { focusState -> ... }
  • Modifier.onKeyEvent { keyEvent -> ... }
  • Modifier.onVisibilityChanged { isVisible -> ... }: Der Callback wird in einer Coroutine aufgerufen, wenn sich die Sichtbarkeit eines Composables nach der konfigurierten Verzögerung ändert.

Kurzübersicht: Wert- im Vergleich zur Lambda-Phase

Wenn Sie einen Statuswert in einem Lambda lesen, wird das Lesen auf eine spätere Phase verschoben. Dadurch werden frühere Phasen übersprungen, wenn sich dieser Status ändert:

Modifikator / Muster Direkter Wert (Zusammensetzung) Lambda-Variante (aufgeschobene Phase) Wenn sich der Status ändert
Offset Modifier.offset(x, y) Modifier.offset { IntOffset(x, y) } Layout (Placement) (Skips Composition)
Alpha / Deckkraft Modifier.alpha(alpha) Modifier.graphicsLayer { this.alpha = alpha } Zeichnen (Komposition und Layout werden übersprungen)
Rotation Modifier.rotate(degrees) Modifier.graphicsLayer { rotationZ = degrees } Zeichnen (Komposition und Layout werden übersprungen)
Scale Modifier.scale(scale) Modifier.graphicsLayer { scaleX = s; scaleY = s } Zeichnen (Komposition und Layout werden übersprungen)
Translation Modifier.padding(...) Modifier.graphicsLayer { translationX = ... } Zeichnen (Komposition und Layout werden übersprungen)
Hintergrundfarbe Modifier.background(color) Modifier.drawBehind { drawRect(color) } Zeichnen (Komposition und Layout werden übersprungen)
Scrollen / Parallaxe Modifier.offset(scroll.dp) Modifier.offset { IntOffset(0, scroll) } Layout (Placement) (Skips Composition)

Modifier.Node-Schnittstellenzuordnung

Bei benutzerdefinierten Modifikatoren, die die leistungsstarke Modifier.Node API verwenden, werden Phasen direkt den Schnittstellen für Knotenfunktionen zugeordnet:

Phase Modifier.Node-Schnittstelle Kernmethoden
Layout (Messen und platzieren) LayoutModifierNode measure(measurable, constraints)
Layout (globale Koordinaten) GlobalPositionAwareModifierNode onGloballyPositioned(coordinates)
Layout (Placement) LayoutAwareModifierNode onRemeasured(size), onPlaced(coordinates)
Zeichnung DrawModifierNode draw(ContentDrawScope)
Eingabe / Zeiger PointerInputModifierNode onPointerEvent(...), onCancelPointerInput()
Semantik SemanticsModifierNode applySemantics(SemanticsPropertyReceiver)
Fokus FocusEventModifierNode onFocusEvent(focusState)