In Compose werden UI-Elemente durch zusammensetzbare Funktionen dargestellt, die beim Aufrufen einen Teil der UI ausgeben. Dieser wird dann einem UI-Baum hinzugefügt, der auf dem Bildschirm gerendert wird. Jedes UI-Element hat ein übergeordnetes Element und möglicherweise viele untergeordnete Elemente. Jedes Element befindet sich auch innerhalb des übergeordneten Elements, das als Position (x, y) und als Größe als width
und height
angegeben wird.
Ü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 beschränken die minimalen und maximalen 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 meldet, kann es definieren, wie seine untergeordneten Elemente relativ zu sich platziert werden. Dies wird ausführlich unter Benutzerdefinierte Layouts erstellen beschrieben.
Das Layout jedes Knotens in der UI-Baumstruktur erfolgt in drei Schritten. Jeder Knoten muss:
- Alle Kinder erfassen
- Größe festlegen
- Untergeordnete Elemente platzieren
Durch die Verwendung von Umfangsbereichen legen Sie fest, wann Sie Ihre untergeordneten Elemente messen und platzieren können.
Die Messung eines Layouts kann nur während der Messung und der Layoutdurchläufe erfolgen. Ein untergeordnetes Element kann nur während der Layoutdurchläufe platziert werden und erst nach der Messung. Aufgrund von Erstellungsbereichen wie MeasureScope
und PlacementScope
wird dies bei der Kompilierung erzwungen.
Layoutmodifikator verwenden
Mit dem Modifikator layout
können Sie ändern, wie ein Element gemessen und angeordnet wird. Layout
ist eine Lambda-Funktion. Zu ihren Parametern gehören das Element, das Sie messen können, das als measurable
übergeben wird, und die eingehenden Einschränkungen dieser zusammensetzbaren Funktion, die als constraints
übergeben werden. Ein benutzerdefinierter Layoutmodifikator kann so aussehen:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Lassen Sie uns ein Text
auf dem Bildschirm anzeigen und den Abstand von oben zur Referenz der ersten Textzeile festlegen. Genau das bewirkt der paddingFromBaseline
-Modifikator. Wir implementieren ihn hier als Beispiel.
Verwenden Sie dazu den layout
-Modifikator, um die zusammensetzbare Funktion manuell auf dem Bildschirm zu platzieren. Hier sehen Sie das gewünschte Verhalten, bei dem der obere Abstand von Text
auf 24.dp
festgelegt ist:
Hier ist der Code zum Erzeugen dieses Abstands:
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) } }
In diesem Code geschieht Folgendes:
- Im Lambda-Parameter
measurable
messen Sie denText
, der durch den messbaren Parameter dargestellt wird, indem Siemeasurable.measure(constraints)
aufrufen. - Sie geben die Größe der zusammensetzbaren Funktion an, indem Sie die Methode
layout(width, height)
aufrufen, die auch ein Lambda zum Platzieren der umschlossenen Elemente erzeugt. In diesem Fall ist das die Höhe zwischen der letzten Referenz und dem hinzugefügten oberen Abstand. - Um die zusammengefassten Elemente auf dem Bildschirm zu positionieren, rufst du
placeable.place(x, y)
auf. Wenn die umschlossenen Elemente nicht platziert werden, sind sie nicht sichtbar. Die Positiony
entspricht dem oberen Abstand – der Position der ersten Referenz des Textes.
Um zu überprüfen, ob dies wie erwartet funktioniert, verwende diesen Modifikator auf Text
:
@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)) } }
Benutzerdefinierte Layouts erstellen
Der layout
-Modifikator ändert nur die aufrufende zusammensetzbare Funktion. Wenn Sie mehrere zusammensetzbare Funktionen messen und für das Layout nutzen möchten, verwenden Sie stattdessen die zusammensetzbare Funktion Layout
. Mit dieser zusammensetzbaren Funktion können Sie Kinder manuell messen und anordnen. Alle übergeordneten Layouts wie Column
und Row
werden mit der zusammensetzbaren Funktion Layout
erstellt.
Erstellen wir eine sehr einfache Version von Column
. 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 layout
-Modifikator 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 Einschränkungen vom Typ Layout
(ohne die Einschränkungen vom Typ minHeight
) eingeschränkt und basierend auf den yPosition
der vorherigen zusammensetzbaren Funktion platziert.
So würde diese benutzerdefinierte zusammensetzbare Funktion verwendet werden:
@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!") } }
Layoutrichtung
Ändern Sie die Layoutrichtung einer zusammensetzbaren Funktion, indem Sie die lokale Zusammensetzung von LocalLayoutDirection
ändern.
Wenn Sie zusammensetzbare Funktionen manuell auf dem Bildschirm platzieren, ist LayoutDirection
Teil des LayoutScope
des layout
-Modifikators oder der zusammensetzbaren Funktion Layout
.
Wenn Sie layoutDirection
verwenden, verwenden Sie place
, um zusammensetzbare Funktionen zu platzieren. Im Gegensatz zur Methode placeRelative
ändert sich place
nicht je nach Layoutrichtung (von links nach rechts oder von rechts nach links).
Benutzerdefinierte Layouts in Aktion
Weitere Informationen zu Layouts und Modifikatoren finden Sie unter Grundlegende Layouts in Compose. Benutzerdefinierte Layouts finden Sie in den Beispielen zum Erstellen benutzerdefinierter Layouts.
Weitere Informationen
Weitere Informationen zu benutzerdefinierten Layouts in Compose finden Sie in den folgenden zusätzlichen Ressourcen.
Videos
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Intrinsische Messungen in Compose-Layouts
- Grafiken in Compose
- Modifikatoren zum Verfassen