Mit Modifikatoren kannst du eine zusammensetzbare Funktion dekorieren oder erweitern. Mit Modifikatoren können Sie folgende Dinge tun:
- Größe, Layout, Verhalten und Darstellung der zusammensetzbaren Funktion ändern
- Informationen wie Bedienungshilfen-Labels hinzufügen
- Nutzereingabe verarbeiten
- Interaktionen auf hoher Ebene hinzufügen, z. B. Elemente anklickbar, scrollbar, ziehbar oder zoombar
Modifikatoren sind standardmäßige Kotlin-Objekte. Um einen Modifikator zu erstellen, rufen Sie eine der Modifier
-Klassenfunktionen auf:
@Composable private fun Greeting(name: String) { Column(modifier = Modifier.padding(24.dp)) { Text(text = "Hello,") Text(text = name) } }
Sie können diese Funktionen verketten, um sie zu erstellen:
@Composable private fun Greeting(name: String) { Column( modifier = Modifier .padding(24.dp) .fillMaxWidth() ) { Text(text = "Hello,") Text(text = name) } }
Beachten Sie, dass im obigen Code verschiedene Modifikatorfunktionen zusammen verwendet werden.
padding
fügt Raum um ein Element hinzu.- Mit
fillMaxWidth
füllt die zusammensetzbare Funktion die maximale Breite aus, die ihr von ihrem übergeordneten Element vorgegeben wird.
Es empfiehlt sich, für alle zusammensetzbaren Funktionen einen modifier
-Parameter zu akzeptieren und diesen Modifikator an das erste untergeordnete Element zu übergeben, das die UI ausgibt.
Das macht Ihren Code wiederverwendbarer und macht sein Verhalten vorhersehbarer und intuitiver. Weitere Informationen finden Sie in den Richtlinien für die Compose API unter Elemente akzeptieren und berücksichtigen einen Modifizierer-Parameter.
Die Reihenfolge der Modifikatoren ist wichtig
Die Reihenfolge der Modifikatorfunktionen ist wichtig. Da jede Funktion Änderungen an dem von der vorherigen Funktion zurückgegebenen Modifier
vornimmt, wirkt sich die Sequenz auf das Endergebnis aus. Hier ein Beispiel:
@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 padding
-Modifikator nach dem Modifizierer clickable
angewendet wurde. Wenn die Reihenfolge der Modifikatoren umgekehrt wird, reagiert das von padding
hinzugefügte Leerzeichen 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 mit integrierten Modifikatoren, mit denen Sie eine zusammensetzbare Funktion gestalten oder erweitern können. Hier sind einige gängige Modifikatoren, mit denen Sie Ihre Layouts anpassen können.
padding
und size
Bei Layouts, die in „Compose“ bereitgestellt werden, werden die untergeordneten Elemente standardmäßig umschlossen. Mit dem Modifikator size
können Sie jedoch eine Größe festlegen:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image(/*...*/) Column { /*...*/ } } }
Beachten Sie, dass die von Ihnen angegebene Größe möglicherweise nicht berücksichtigt wird, wenn sie nicht den Einschränkungen des übergeordneten Layouts entspricht. Wenn die zusammensetzbare Größe unabhängig von den eingehenden Einschränkungen festgelegt werden muss, verwenden Sie den Modifizierer requiredSize
:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.requiredSize(150.dp) ) Column { /*...*/ } } }
In diesem Beispiel ist die Höhe von Image
, auch wenn das übergeordnete Element height
auf 100.dp
festgelegt ist, 150.dp
, da der requiredSize
-Modifikator Vorrang hat.
Wenn ein untergeordnetes Layout die gesamte für das übergeordnete Element zulässige Höhe ausfüllen soll, fügen Sie den Modifikator fillMaxHeight
hinzu. Schreiben Sie auch fillMaxSize
und fillMaxWidth
:
@Composable fun ArtistCard(/*...*/) { Row( modifier = Modifier.size(width = 400.dp, height = 100.dp) ) { Image( /*...*/ modifier = Modifier.fillMaxHeight() ) Column { /*...*/ } } }
Wenn Sie das gesamte Element um einen Innenrand versehen möchten, legen Sie einen padding
-Modifikator fest.
Wenn Sie einen Abstand über einer Textreferenz hinzufügen möchten, sodass ein bestimmter Abstand vom oberen Rand des Layouts zur Grundlinie erreicht wird, 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) } } }
Abweichung
Um ein Layout relativ zur ursprünglichen Position zu positionieren, fügen Sie den Modifikator offset
hinzu und legen Sie den Versatz in der x- und y-Achse fest.
Offsets können positiv oder nicht positiv sein. Der Unterschied zwischen padding
und offset
besteht darin, dass das Hinzufügen eines offset
zu einer zusammensetzbaren Funktion seine Messungen nicht ändert:
@Composable fun ArtistCard(artist: Artist) { Row(/*...*/) { Column { Text(artist.name) Text( text = artist.lastSeenOnline, modifier = Modifier.offset(x = 4.dp) ) } } }
Der offset
-Modifikator wird horizontal gemäß der Layoutrichtung angewendet.
In einem Rechts-nach-rechts-Kontext wird ein positives offset
-Element das Element nach rechts und in einem Links-nach-links- Kontext nach links verschoben.
Wenn Sie einen Offset ohne Berücksichtigung der Layoutrichtung festlegen müssen, verwenden Sie den absoluteOffset
-Modifikator, bei dem ein positiver Offset-Wert das Element immer nach rechts verschiebt.
Der offset
-Modifikator stellt zwei Überlasten bereit: offset
, das die Offsets als Parameter annimmt, und offset
, das ein Lambda annimmt.
Ausführlichere Informationen dazu, wann Sie welche dieser Methoden verwenden sollten und wie Sie die Leistung optimieren, finden Sie im Abschnitt Leistung verfassen – Lesevorgänge so lange wie möglich zurückstellen.
Sicherheit des Umfangs in Compose
In der Funktion „Compose“ gibt es Modifikatoren, die nur verwendet werden können, wenn sie auf untergeordnete Elemente bestimmter zusammensetzbarer Funktionen angewendet werden. Beim Erstellen wird dies mithilfe von benutzerdefinierten Bereichen erzwungen.
Wenn Sie beispielsweise ein untergeordnetes Element so groß wie das übergeordnete Element Box
machen möchten, ohne die Größe Box
zu beeinflussen, verwenden Sie den Modifizierer matchParentSize
. matchParentSize
ist nur in BoxScope
verfügbar.
Daher kann sie nur für ein untergeordnetes Element innerhalb eines übergeordneten Box
-Elements verwendet werden.
Die Bereichssicherheit verhindert, dass Sie Modifikatoren hinzufügen, die in anderen zusammensetzbaren Funktionen und Bereichen nicht funktionieren, und spart Zeit durch Ausprobieren.
Modifikatoren für den Bereich informieren das übergeordnete Element über einige Informationen, die es über das untergeordnete Element wissen sollte. Diese werden auch als übergeordnete Datenmodifikatoren bezeichnet. Ihre internen Strukturen unterscheiden sich von den Modifizierern für allgemeine Zwecke, aber in Bezug auf die Verwendung spielen diese Unterschiede keine Rolle.
matchParentSize
in Box
Wie bereits erwähnt, müssen Sie den matchParentSize
-Modifikator verwenden, wenn ein untergeordnetes Layout die gleiche Größe wie ein übergeordnetes Box
-Element haben soll, ohne dass sich dies auf die Box
-Größe auswirkt.
matchParentSize
ist nur innerhalb eines Box
-Bereichs verfügbar, d. h., er gilt nur für direkte untergeordnete Elemente von Box
zusammensetzbaren Funktionen.
Im folgenden Beispiel übernimmt das untergeordnete Spacer
seine Größe vom übergeordneten Box
, das wiederum seine Größe von den größten untergeordneten Elementen ü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 das Spacer
den gesamten verfügbaren Speicherplatz des übergeordneten Elements einnehmen. Dadurch wird das übergeordnete Element wiederum erweitert und füllt den gesamten verfügbaren Bereich aus.
weight
in Row
und Column
Wie Sie im vorherigen Abschnitt zum Thema Abstand und Größe gesehen haben, wird eine zusammensetzbare Größe standardmäßig durch den Inhalt definiert, der umgebrochen wird. Sie können eine zusammensetzbare Größe so festlegen, dass sie innerhalb des übergeordneten Elements flexibel ist. Verwenden Sie dazu den weight
-Modifikator, der nur in RowScope
und ColumnScope
verfügbar ist.
Nehmen wir eine Row
, die zwei zusammensetzbare Box
-Elemente enthält.
Das erste Feld wird doppelt so klein wie weight
der zweiten Box, also doppelt so breit. Da Row
210.dp
breit ist, ist der erste Box
140.dp
und der zweite 70.dp
breit:
@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 Modifier
-Schnittstelle erstellt, die eine geordnete, unveränderliche Liste einzelner Modifier.Elements
darstellt.
Jede Modifier.Element
repräsentiert ein individuelles Verhalten, z. B. Layout-, Zeichen- und Grafikverhalten, alle gestenbezogenen, fokussierten und semantischen Verhaltensweisen sowie Geräteeingabeereignisse. Die Reihenfolge ist entscheidend: Modifikatorelemente,
die zuerst hinzugefügt werden, werden zuerst angewendet.
Manchmal kann es vorteilhaft sein, dieselben Modifikatorketteninstanzen in mehreren zusammensetzbaren Funktionen wiederzuverwenden, indem Sie sie in Variablen extrahieren und in höhere Bereiche schieben. Es kann aus verschiedenen Gründen dazu beitragen, die Lesbarkeit von Code oder die Leistung Ihrer Anwendung zu verbessern:
- Die Neuzuweisung der Modifikatoren wird nicht wiederholt, wenn zusammensetzbare Funktionen neu zusammengesetzt werden, in denen sie verwendet werden.
- Modifikatorketten können potenziell sehr lang und komplex sein. Die Wiederverwendung derselben Instanz einer Kette kann daher die Arbeitslast entlasten, die die Compose-Laufzeit beim Vergleichen ausführen muss.
- Diese Extraktion fördert die Codereinheit, Konsistenz und Verwaltbarkeit auf der gesamten Codebasis
Best Practices für die Wiederverwendung von Modifizierern
Erstellen Sie Ihre eigenen Modifier
-Ketten und extrahieren Sie sie, um sie in mehreren zusammensetzbaren Komponenten wiederzuverwenden. Sie können einen Modifizierer lediglich speichern, da es sich um datenähnliche Objekte handelt:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp)
Modifikatoren bei der Beobachtung von sich häufig ändernden Zustand extrahieren und wiederverwenden
Wenn sich die Zustände in zusammensetzbaren Funktionen wie Animationsstatus oder scrollState
häufig ändern, kann es zu einer erheblichen Anzahl von Neuzusammensetzungen kommen. In diesem Fall werden die Modifikatoren bei jeder Neuzusammensetzung und potenziell 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 können Sie dieselbe Instanz des Modifizierers erstellen, extrahieren, wiederverwenden und 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 ) }
Modifizierer ohne Umfang extrahieren und wiederverwenden
Modifikatoren können keinen Geltungsbereich haben oder auf eine bestimmte zusammensetzbare Funktion beschränkt sein. Modifikatoren ohne Bereich können problemlos als einfache Variablen außerhalb von zusammensetzbaren Funktionen extrahiert werden:
val reusableModifier = Modifier .fillMaxWidth() .background(Color.Red) .padding(12.dp) @Composable fun AuthorField() { HeaderText( // ... modifier = reusableModifier ) SubtitleText( // ... modifier = reusableModifier ) }
Dies kann besonders in Kombination mit Lazy-Layouts von Vorteil sein. In den meisten Fällen ist es sinnvoll, dass alle potenziell signifikanten Elemente 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, ) } } }
Bereichsspezifische Modifikatoren extrahieren und wiederverwenden
Wenn Sie Modifikatoren verwenden, die sich auf bestimmte zusammensetzbare Funktionen beziehen, können Sie diese auf die höchstmögliche Ebene extrahieren und gegebenenfalls 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 bereichsspezifischen Modifikatoren nur an direkte untergeordnete Elemente mit demselben Bereich übergeben. Weitere Informationen dazu, warum das wichtig ist, finden Sie im Abschnitt Sicherheit des Bereichs in Composer:
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 der extrahierten 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)
Beachte aber, dass die Reihenfolge der Modifikatoren wichtig ist.
Weitere Informationen
Wir stellen eine vollständige Liste der Modifikatoren mit ihren Parametern und Bereichen zur Verfügung.
Weitere Übungen zum Verwenden von Modifikatoren finden Sie im Codelab zu grundlegenden Layouts im Codelab oder im Now in Android-Repository.
Weitere Informationen zu benutzerdefinierten Modifikatoren und zu ihrer Erstellung finden Sie in der Dokumentation zu Benutzerdefinierte Layouts: Verwendung des Layout-Modifikators.
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grundlagen zum Verfassen von Layouts
- Editoraktionen {:#editor-actions}
- Benutzerdefinierte Layouts {:#custom-layouts }