Mit Modifikatoren können Sie eine zusammensetzbare Funktion dekorieren oder erweitern. Mit Modifikatoren können Sie Folgendes tun:
- Größe, Layout, Verhalten und Darstellung des Compose-Elements ändern
- Informationen wie Labels zur Barrierefreiheit hinzufügen
- Nutzereingabe verarbeiten
- Interaktionen auf hoher Ebene hinzufügen, z. B. ein Element anklickbar, scrollbar, ziehbar oder zoombar machen
Modifikatoren sind Standard-Kotlin-Objekte. Erstellen Sie einen Modifikator, indem Sie eine der Klassenfunktionen von Modifier aufrufen:
@Composable private fun Greeting(name: String) { Column(modifier = Modifier.padding(24.dp)) { Text(text = "Hello,") Text(text = name) } }
Sie können diese Funktionen miteinander verketten, um sie zu kombinieren:
@Composable private fun Greeting(name: String) { Column( modifier = Modifier .padding(24.dp) .fillMaxWidth() ) { Text(text = "Hello,") Text(text = name) } }
Im Code oben werden verschiedene Modifikatorfunktionen zusammen verwendet.
paddingfügt Platz um ein Element herum hinzu.- Mit
fillMaxWidthwird die maximale Breite des übergeordneten Elements für die komponierbare Funktion festgelegt.
Es empfiehlt sich, dass alle Composables einen modifier-Parameter akzeptieren und diesen Modifikator an das erste untergeordnete Element übergeben, das die UI ausgibt.
Dadurch wird Ihr Code wiederverwendbarer und sein Verhalten vorhersehbarer und intuitiver. Weitere Informationen finden Sie in den Compose API-Richtlinien unter Elemente akzeptieren und berücksichtigen einen Modifier-Parameter.
Reihenfolge der Modifikatoren ist wichtig
Die Reihenfolge der Modifikatorfunktionen ist wichtig. Da jede Funktion Änderungen an der von der vorherigen Funktion zurückgegebenen Modifier vornimmt, wirkt sich die Reihenfolge auf das Endergebnis aus. Sehen wir uns ein Beispiel an:
@Composable fun ArtistCard(/*...*/) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { // rest of the implementation } }
Im Code oben ist der gesamte Bereich anklickbar, einschließlich des umgebenden Abstands, da der Modifikator padding nach dem Modifikator clickable angewendet wurde. Wenn die Reihenfolge der Modifikatoren umgekehrt wird, reagiert der von padding hinzugefügte Bereich nicht auf Nutzereingaben:
@Composable fun ArtistCard(/*...*/) { val padding = 16.dp Column( Modifier .padding(padding) .clickable(onClick = onClick) .fillMaxWidth() ) { // rest of the implementation } }
Integrierte Modifikatoren
Jetpack Compose bietet eine Liste integrierter Modifikatoren, mit denen Sie eine zusammensetzbare Funktion dekorieren oder erweitern können. Hier sind einige gängige Modifikatoren, mit denen Sie Ihre Layouts anpassen können.
padding und size
Standardmäßig umschließen in Compose bereitgestellte Layouts ihre untergeordneten Elemente. Sie können jedoch mit dem Modifikator size eine Größe festlegen:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image(/*...*/) Column { /*...*/ } } }
Die von Ihnen angegebene Größe wird möglicherweise nicht berücksichtigt, wenn sie nicht den Einschränkungen des übergeordneten Elements des Layouts entspricht. Wenn die Größe der zusammensetzbaren Funktion unabhängig von den eingehenden Einschränkungen festgelegt werden soll, verwenden Sie den Modifikator requiredSize:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.requiredSize(150.dp) ) Column { /*...*/ } } }
In diesem Beispiel beträgt die Höhe des Image 150.dp, obwohl das übergeordnete height auf 100.dp festgelegt ist, da der Modifikator requiredSize Vorrang hat.
Wenn ein untergeordnetes Layout die gesamte vom übergeordneten Element zugelassene Höhe ausfüllen soll, fügen Sie den Modifikator fillMaxHeight hinzu. Compose bietet auch fillMaxSize und fillMaxWidth:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.fillMaxHeight() ) Column { /*...*/ } } }
Wenn Sie ein Element rundherum mit Padding versehen möchten, legen Sie einen padding-Modifikator fest.
Die Parameter start und end von padding folgen der Layoutrichtung. Wenn Sie den linken oder rechten Rand unabhängig von der Layoutrichtung auffüllen möchten, verwenden Sie absolutePadding mit den Parametern left und right.
Wenn Sie über einer Grundlinie Padding hinzufügen möchten, um einen bestimmten Abstand vom oberen Rand des Layouts zur Grundlinie zu erreichen, verwenden Sie den Modifikator paddingFromBaseline:
@Composable fun ArtistCard(artist: Artist) { Row(/*...*/) { Column { Text( text = artist.name, modifier = Modifier.paddingFromBaseline(top = 50.dp) ) Text(artist.lastSeenOnline) } } }
Offset
Wenn Sie ein Layout relativ zu seiner ursprünglichen Position positionieren möchten, fügen Sie den Modifikator offset hinzu und legen Sie den Versatz auf der X- und Y-Achse fest.
Offsets können sowohl positiv als auch nicht positiv sein. Der Unterschied zwischen padding und offset besteht darin, dass das Hinzufügen eines offset zu einer zusammensetzbaren Funktion die Messungen nicht ändert:
@Composable fun ArtistCard(artist: Artist) { Row(/*...*/) { Column { Text(artist.name) Text( text = artist.lastSeenOnline, modifier = Modifier.offset(x = 4.dp) ) } } }
Der Modifikator offset wird horizontal entsprechend der Layoutrichtung angewendet.
In einem Links-nach-rechts-Kontext verschiebt ein positiver offset-Wert das Element nach rechts, während es in einem Rechts-nach-links-Kontext nach links verschoben wird.
Wenn du einen Versatz festlegen möchtest, ohne die Layoutrichtung zu berücksichtigen, verwende den Modifikator absoluteOffset. Bei diesem Modifikator wird das Element durch einen positiven Versatzwert immer nach rechts verschoben.
Der Modifikator offset bietet zwei Überladungen: offset, die die Offsets als Parameter verwendet, und offset, die ein Lambda verwendet.
Weitere Informationen dazu, wann die einzelnen Optionen verwendet werden sollten und wie die Leistung optimiert werden kann, finden Sie im Abschnitt Compose-Leistung – Lesevorgänge so lange wie möglich aufschieben.
Sicherheit des Bereichs in Compose
In Compose gibt es Modifikatoren, die nur verwendet werden können, wenn sie auf untergeordnete Elemente bestimmter Composables angewendet werden. Compose erzwingt dies mithilfe von benutzerdefinierten Bereichen.
Wenn Sie beispielsweise ein untergeordnetes Element so groß wie das übergeordnete Box machen möchten, ohne die Größe des Box zu beeinflussen, verwenden Sie den Modifikator matchParentSize. matchParentSize ist nur in BoxScope verfügbar.
Daher kann es nur für ein untergeordnetes Element innerhalb eines übergeordneten Box-Elements verwendet werden.
Die Bereichssicherheit verhindert, dass Sie Modifikatoren hinzufügen, die in anderen Composables und Bereichen nicht funktionieren würden. So sparen Sie Zeit, die Sie sonst mit Ausprobieren verbringen würden.
Bereichsbezogene Modifikatoren benachrichtigen das übergeordnete Element über Informationen, die das übergeordnete Element über das untergeordnete Element wissen sollte. Diese werden auch als übergeordnete Datenmodifikatoren bezeichnet. Ihre internen Abläufe unterscheiden sich von den Modifikatoren für allgemeine Zwecke, aber aus Sicht der Nutzung spielen diese Unterschiede keine Rolle.
matchParentSize in Box
Wie bereits erwähnt, können Sie mit dem Modifikator matchParentSize ein untergeordnetes Layout so konfigurieren, dass es dieselbe Größe wie ein übergeordnetes Box hat, ohne die Größe des Box zu beeinflussen.
Beachten Sie, dass matchParentSize nur innerhalb eines Box-Bereichs verfügbar ist. Das bedeutet, dass es nur für direkte untergeordnete Elemente von Box-Kompositionen gilt.
Im folgenden Beispiel übernimmt das untergeordnete Element Spacer die Größe des übergeordneten Elements Box, das wiederum die Größe des größten untergeordneten Elements übernimmt, in diesem Fall ArtistCard.
@Composable fun MatchParentSizeComposable() { Box { Spacer( Modifier .matchParentSize() .background(Color.LightGray) ) ArtistCard() } }
Wenn fillMaxSize anstelle von matchParentSize verwendet würde, würde Spacer den gesamten verfügbaren Platz des übergeordneten Elements einnehmen, was wiederum dazu führen würde, dass das übergeordnete Element erweitert wird und den gesamten verfügbaren Platz einnimmt.
weight in Row und Column
Wie Sie im vorherigen Abschnitt zu Padding und Größe gesehen haben, wird die Größe einer zusammensetzbaren Funktion standardmäßig durch den Inhalt definiert, den sie umschließt. Mit dem Modifikator weight, der nur in RowScope und ColumnScope verfügbar ist, können Sie die Größe einer zusammensetzbaren Funktion innerhalb ihres übergeordneten Elements flexibel festlegen.
Nehmen wir eine Row, die zwei Box-Kompositionen enthält.
Das erste Feld hat den doppelten weight-Wert des zweiten Felds und ist daher doppelt so breit. Da der Row 210.dp breit ist, ist der erste Box 140.dp breit und der zweite 70.dp:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.fillMaxWidth() ) { Image( /*...*/ modifier = Modifier.weight(2f) ) Column( modifier = Modifier.weight(1f) ) { /*...*/ } } }
Modifikatoren extrahieren und wiederverwenden
Mehrere Modifikatoren können miteinander verkettet werden, um eine zusammensetzbare Funktion zu dekorieren oder zu erweitern. Diese Kette wird über die Schnittstelle Modifier erstellt, die eine geordnete, unveränderliche Liste einzelner Modifier.Elements darstellt.
Jeder Modifier.Element steht für ein einzelnes Verhalten, z. B. Layout-, Zeichen- und Grafikverhalten, alle gestenbezogenen, Fokus- und Semantikverhalten sowie Geräteeingabeereignisse. Die Reihenfolge ist wichtig: Modifikatorelemente, die zuerst hinzugefügt werden, werden auch zuerst angewendet.
Manchmal kann es von Vorteil sein, dieselben Modifikatorketteninstanzen in mehreren Composables wiederzuverwenden, indem sie in Variablen extrahiert und in höhere Bereiche verschoben werden. Dies kann die Lesbarkeit des Codes verbessern oder die Leistung Ihrer App aus mehreren Gründen verbessern:
- Die Neuzuweisung der Modifikatoren wird nicht wiederholt, wenn eine Neuzusammensetzung für die Composables erfolgt, die sie verwenden.
- Modifikatorketten können potenziell sehr lang und komplex sein. Wenn Sie dieselbe Instanz einer Kette wiederverwenden, kann dies die Arbeitslast der Compose-Laufzeit beim Vergleichen verringern.
- Diese Extraktion fördert die Sauberkeit, Konsistenz und Wartbarkeit des Codes in der gesamten Codebasis.
Best Practices für die Wiederverwendung von Modifikatoren
Sie können eigene Modifier-Ketten erstellen und extrahieren, um sie in mehreren zusammensetzbaren Komponenten wiederzuverwenden. Es ist völlig in Ordnung, nur einen Modifikator zu speichern, da es sich um datenähnliche Objekte handelt:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp)
Modifikatoren extrahieren und wiederverwenden, wenn sich der Status häufig ändert
Wenn Sie sich häufig ändernde Zustände innerhalb von Composables beobachten, z. B. Animationszustände oder scrollState, kann es zu einer erheblichen Anzahl von Neuzusammensetzungen kommen. In diesem Fall werden Ihre Modifikatoren bei jeder Neuzusammensetzung und möglicherweise für jeden Frame zugewiesen:
@Composable fun LoadingWheelAnimation() { val animatedState = animateFloatAsState(/*...*/) LoadingWheel( // Creation and allocation of this modifier will happen on every frame of the animation! modifier = Modifier .padding(12.dp) .background(Color.Gray), animatedState = animatedState ) }
Stattdessen kannst du dieselbe Instanz des Modifikators erstellen, extrahieren und wiederverwenden und sie so an die zusammensetzbare Funktion übergeben:
// Now, the allocation of the modifier happens here: val reusableModifier = Modifier .padding(12.dp) .background(Color.Gray) @Composable fun LoadingWheelAnimation() { val animatedState = animateFloatAsState(/*...*/) LoadingWheel( // No allocation, as we're just reusing the same instance modifier = reusableModifier, animatedState = animatedState ) }
Unscoped-Modifikatoren extrahieren und wiederverwenden
Modifikatoren können ohne Bereich oder auf eine bestimmte zusammensetzbare Funktion beschränkt sein. Modifikatoren ohne Bereich können Sie ganz einfach als einfache Variablen außerhalb von Composables extrahieren:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) @Composable fun AuthorField() { HeaderText( // ... modifier = reusableModifier ) SubtitleText( // ... modifier = reusableModifier ) }
Das kann besonders in Kombination mit Lazy-Layouts von Vorteil sein. In den meisten Fällen sollten alle Ihre (potenziell vielen) Elemente genau dieselben Modifikatoren haben:
val reusableItemModifier = Modifier .padding(bottom = 12.dp) .size(216.dp) .clip(CircleShape) @Composable private fun AuthorList(authors: List<Author>) { LazyColumn { items(authors) { AsyncImage( // ... modifier = reusableItemModifier, ) } } }
Bereichsbezogene Modifikatoren extrahieren und wiederverwenden
Wenn Sie mit Modifikatoren arbeiten, die auf bestimmte Composables beschränkt sind, können Sie sie auf die höchstmögliche Ebene extrahieren und bei Bedarf wiederverwenden:
Column(/*...*/) { val reusableItemModifier = Modifier .padding(bottom = 12.dp) // Align Modifier.Element requires a ColumnScope .align(Alignment.CenterHorizontally) .weight(1f) Text1( modifier = reusableItemModifier, // ... ) Text2( modifier = reusableItemModifier // ... ) // ... }
Sie sollten die extrahierten, bereichsbezogenen Modifikatoren nur an die direkten untergeordneten Elemente mit demselben Bereich übergeben. Weitere Informationen dazu, warum dies wichtig ist, finden Sie im Abschnitt Sicherheit des Bereichs in Compose:
Column(modifier = Modifier.fillMaxWidth()) { // Weight modifier is scoped to the Column composable val reusableItemModifier = Modifier.weight(1f) // Weight will be properly assigned here since this Text is a direct child of Column Text1( modifier = reusableItemModifier // ... ) Box { Text2( // Weight won't do anything here since the Text composable is not a direct child of Column modifier = reusableItemModifier // ... ) } }
Weitere Verkettung extrahierter Modifikatoren
Sie können die extrahierten Modifikatorketten weiter verketten oder anhängen, indem Sie die Funktion .then() aufrufen:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) // Append to your reusableModifier reusableModifier.clickable { /*...*/ } // Append your reusableModifier otherModifier.then(reusableModifier)
Beachten Sie, dass die Reihenfolge der Modifikatoren wichtig ist.
Weitere Informationen
Wir stellen eine vollständige Liste der Modifikatoren mit ihren Parametern und Bereichen bereit.
Wenn Sie mehr über die Verwendung von Modifikatoren erfahren möchten, können Sie auch das Codelab „Grundlegende Layouts in Compose“ durchgehen oder das Now in Android-Repository aufrufen.
Weitere Informationen zu benutzerdefinierten Modifikatoren und ihrer Erstellung finden Sie in der Dokumentation zu Benutzerdefinierten Layouts – Layoutmodifikator verwenden.
Empfehlungen für Sie
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grundlagen des Compose-Layouts
- Editor-Aktionen {:#editor-actions}
- Benutzerdefinierte Layouts {:#custom-layouts }