In Compose werden UI-Elemente durch zusammensetzbare 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 möglicherweise viele untergeordnete Elemente. Jedes Element befindet sich auch innerhalb seines übergeordneten Elements, das als (x, y)-Position und als Größe (width
und height
) angegeben wird.
Eltern definieren die Einschränkungen für ihre untergeordneten Elemente. Ein Element wird aufgefordert, seine Größe innerhalb dieser Einschränkungen zu definieren. Mit Einschränkungen wird der minimale und maximale width
- und height
-Wert eines Elements eingeschränkt. 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 festlegen, wie seine untergeordneten Elemente relativ zu ihm platziert werden sollen. Dies wird ausführlich unter Benutzerdefinierte Layouts erstellen beschrieben.
Das Layout jedes Knotens im UI-Baum erfolgt in drei Schritten. Jeder Knoten muss:
- Untergeordnete Elemente messen
- Größe selbst bestimmen
- Untergeordnete Elemente platzieren
Die Verwendung von Bereichen definiert, wann Sie Ihre Kinder messen und platzieren können.
Ein Layout kann nur während der Mess- und Layout-Durchläufe gemessen werden. Ein untergeordnetes Element kann nur während der Layout-Durchläufe platziert werden (und erst, nachdem es gemessen wurde). Aufgrund von Compose-Bereichen wie MeasureScope
und PlacementScope
wird dies zur Kompilierzeit erzwungen.
Layout-Modifikator verwenden
Mit dem Modifikator layout
können Sie ändern, wie ein Element gemessen und angeordnet wird. Layout
ist ein Lambda. Zu den Parametern gehören das messbare Element, das als measurable
übergeben wird, und die eingehenden Einschränkungen des zusammensetzbaren Elements, die als constraints
übergeben werden. Ein benutzerdefinierter Layoutmodifikator kann so aussehen:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wir lassen ein Text
auf dem Bildschirm anzeigen und steuern den Abstand vom oberen Rand zur Grundlinie der ersten Textzeile. Genau das macht der Modifikator paddingFromBaseline
. Wir implementieren ihn hier als Beispiel.
Verwenden Sie dazu den Modifier layout
, um die Composable manuell auf dem Bildschirm zu platzieren. So sieht das gewünschte Verhalten aus, wenn der obere Innenabstand des Text
auf 24.dp
festgelegt ist:
Mit diesem Code wird der Abstand erzeugt:
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
measurable
wird dieText
, die durch den messbaren Parameter dargestellt wird, durch Aufrufen vonmeasurable.measure(constraints)
gemessen. - Sie geben die Größe des Composables an, indem Sie die Methode
layout(width, height)
aufrufen. Diese Methode gibt auch ein Lambda zurück, mit dem die umschlossenen Elemente platziert werden. In diesem Fall ist es die Höhe zwischen der letzten Baseline und dem hinzugefügten oberen Padding. - Die umbrochenen Elemente werden auf dem Bildschirm positioniert, indem Sie
placeable.place(x, y)
aufrufen. Wenn die umbrochenen Elemente nicht platziert werden, sind sie nicht sichtbar. Diey
-Position entspricht dem oberen Innenabstand – der Position der ersten Grundlinie des Texts.
Um zu prüfen, ob dies wie erwartet funktioniert, verwenden Sie diesen Modifikator für einen 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 Modifizierer layout
ändert nur die Calling-Composable. Wenn Sie mehrere Composables messen und anordnen möchten, verwenden Sie stattdessen das Composable Layout
. Mit dieser Composable-Funktion können Sie untergeordnete Elemente manuell messen und anordnen. Alle Layouts auf höherer Ebene wie Column
und Row
werden mit der zusammensetzbaren Funktion Layout
erstellt.
Wir erstellen 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 Modifikator layout
ist measurables
die Liste der untergeordneten Elemente, die gemessen werden müssen, und constraints
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 Composables werden durch die Layout
-Einschränkungen (ohne die minHeight
-Einschränkungen) eingeschränkt und basierend auf dem yPosition
des vorherigen Composables platziert.
So wird das benutzerdefinierte Composable 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!") } }
Layoutrichtung
Sie können die Layoutrichtung eines Composables ändern, indem Sie die lokale Komposition LocalLayoutDirection
ändern.
Wenn Sie zusammensetzbare Funktionen manuell auf dem Bildschirm platzieren, ist LayoutDirection
Teil von LayoutScope
des layout
-Modifiers oder der Layout
-zusammensetzbaren Funktion.
Wenn Sie layoutDirection
verwenden, platzieren Sie Composables mit place
. Im Gegensatz zur Methode placeRelative
ändert sich place
nicht basierend auf der Layoutrichtung (von links nach rechts oder von rechts nach links).
Benutzerdefinierte Layouts in der Praxis
Weitere Informationen zu Layouts und Modifikatoren finden Sie unter Einfache Layouts in Compose. Beispiele für benutzerdefinierte Layouts finden 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 dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Integrierte Messungen in Compose-Layouts
- Grafiken in Compose
- Modifizierer für „Verfassen“