In Compose werden UI-Elemente durch die zusammensetzbaren Funktionen dargestellt, die bei Aufruf ein UI-Element ausgeben, das dann einem UI-Baum hinzugefügt wird, der auf dem Bildschirm gerendert wird. Jedes UI-Element hat ein übergeordnetes Element und potenziell viele untergeordnete Elemente. Jedes Element befindet sich auch innerhalb seines übergeordneten Elements, angegeben als (x, y)-Position, und hat eine Größe, angegeben als width und height.
Übergeordnete Elemente definieren die Einschränkungen für ihre untergeordneten Elemente. Ein Element wird aufgefordert, seine Größe innerhalb dieser Einschränkungen zu definieren. Einschränkungen begrenzen die minimale und maximale width und height eines Elements. Wenn ein Element untergeordnete Elemente hat, kann es jedes untergeordnete Element messen, um seine Größe zu bestimmen. Sobald ein Element seine eigene Größe bestimmt
und gemeldet hat, kann es definieren, wie seine untergeordneten
Elemente relativ zu ihm platziert werden sollen. Weitere Informationen finden Sie unter Benutzerdefinierte
Layouts erstellen.
Das Layout jedes Knotens im UI-Baum erfolgt in drei Schritten. Jeder Knoten muss:
- Alle untergeordneten Elemente messen
- Seine eigene Größe bestimmen
- Seine untergeordneten Elemente platzieren
Die Verwendung von Bereichen definiert, wann Sie Ihre untergeordneten Elemente messen und platzieren können.
Das Messen eines Layouts ist nur während der Mess- und Layoutdurchläufe möglich. Ein untergeordnetes Element kann nur während der Layoutdurchläufe platziert werden (und erst, nachdem es gemessen wurde). Aufgrund von Compose-Bereichen wie
MeasureScope,
und PlacementScope,
wird dies zur Kompilierzeit erzwungen.
Layout-Modifizierer verwenden
Mit dem Modifizierer layout können Sie ändern, wie ein Element gemessen und angeordnet wird. Layout ist eine Lambda-Funktion. Zu den Parametern gehören das Element, das Sie messen können, übergeben als measurable, und die eingehenden Einschränkungen dieser zusammensetzbaren Funktion, übergeben als constraints. Ein benutzerdefinierter Layout-Modifizierer kann so aussehen:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Zeigen Sie einen Text auf dem Bildschirm an und steuern Sie den Abstand von oben zur Grundlinie der ersten Textzeile. Genau das macht der Modifizierer paddingFromBaseline. Sie implementieren ihn hier als Beispiel.
Verwenden Sie dazu den Modifizierer layout, um die zusammensetzbare Funktion manuell auf dem Bildschirm zu platzieren. Hier ist das resultierende Verhalten, bei dem der obere Abstand von Text auf 24.dp festgelegt ist:
paddingFromBaseline.
Hier ist der Code, um diesen Abstand zu erzeugen:
fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp ) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] != AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) } }
Das passiert in diesem Code:
- Im Lambda-Parameter
measurablemessen Sie denText, der durch den Parameter „measurable“ dargestellt wird, indem Siemeasurable.measure(constraints)aufrufen. - Sie geben die Größe der zusammensetzbaren Funktion an, indem Sie die Methode
layout(width, height)aufrufen. Diese Methode gibt auch eine Lambda-Funktion zurück, die zum Platzieren der umschlossenen Elemente verwendet wird. In diesem Fall ist es die Höhe zwischen der letzten Grundlinie und dem hinzugefügten oberen Abstand. - Sie positionieren die umschlossenen Elemente auf dem Bildschirm, indem Sie
placeable.place(x, y)aufrufen. Wenn die umschlossenen Elemente nicht platziert werden, sind sie nicht sichtbar. Diey-Position entspricht dem oberen Abstand: der Position der ersten Grundlinie des Texts.
Verwenden Sie diesen Modifizierer für einen Text, um zu prüfen, ob er wie erwartet funktioniert:
@Preview @Composable fun TextWithPaddingToBaselinePreview() { MyApplicationTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } } @Preview @Composable fun TextWithNormalPaddingPreview() { MyApplicationTheme { Text("Hi there!", Modifier.padding(top = 32.dp)) } }
Text angewendet und in der Vorschau angezeigt.
Benutzerdefinierte Layouts erstellen
Der Modifizierer layout ändert nur die aufrufende zusammensetzbare Funktion. Wenn Sie mehrere zusammensetzbare Funktionen messen und anordnen möchten, verwenden Sie stattdessen die Layout zusammensetzbare Funktion. Mit dieser zusammensetzbaren Funktion können Sie untergeordnete Elemente manuell messen und anordnen. Alle Layouts höherer Ebene wie Column und Row werden mit der zusammensetzbaren Funktion Layout erstellt.
In diesem Beispiel wird eine sehr einfache Version von Column erstellt. Die meisten benutzerdefinierten Layouts folgen diesem Muster:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // measure and position children given constraints logic here // ... } }
Ähnlich wie beim Modifizierer layout ist measurables die Liste der untergeordneten Elemente, die gemessen werden müssen, und constraints sind die Einschränkungen des übergeordneten Elements.
Nach derselben Logik wie zuvor kann MyBasicColumn so implementiert werden:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // Don't constrain child views further, measure them with given constraints // List of measured children val placeables = measurables.map { measurable -> // Measure each children measurable.measure(constraints) } // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // Track the y co-ord we have placed children up to var yPosition = 0 // Place children in the parent layout placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition) // Record the y co-ord placed up to yPosition += placeable.height } } } }
Die untergeordneten zusammensetzbaren Funktionen werden durch die Layout-Einschränkungen (ohne die minHeight-Einschränkungen) eingeschränkt und basierend auf der yPosition der vorherigen zusammensetzbaren Funktion platziert.
So wird die benutzerdefinierte zusammensetzbare Funktion verwendet:
@Composable fun CallingComposable(modifier: Modifier = Modifier) { MyBasicColumn(modifier.padding(8.dp)) { Text("MyBasicColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } }
Column-Implementierung.
Layoutrichtung
Ändern Sie die Layoutrichtung einer zusammensetzbaren Funktion, indem Sie die
LocalLayoutDirection lokale Zusammensetzung ändern.
Wenn Sie zusammensetzbare Funktionen manuell auf dem Bildschirm platzieren, ist die LayoutDirection Teil des LayoutScope des Modifizierers layout oder der zusammensetzbaren Funktion Layout.
Wenn Sie layoutDirection verwenden, platzieren Sie zusammensetzbare Funktionen mit place. Anders als bei der
placeRelative
Methode ändert sich place nicht basierend auf der Layoutrichtung
(von links nach rechts oder von rechts nach links).
Benutzerdefinierte Layouts in Aktion
Weitere Informationen zu Layouts und Modifizierern finden Sie unter Einfache Layouts in Compose, Benutzerdefinierte Layouts in Aktion sehen Sie in den Compose-Beispielen, in denen benutzerdefinierte Layouts erstellt werden.
Weitere Informationen
Weitere Informationen zu benutzerdefinierten Layouts in Compose finden Sie in den folgenden zusätzlichen Ressourcen.
Videos
Empfehlungen für Sie
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist
- Intrinsic measurements in Compose layouts
- Graphics in Compose
- Compose modifiers