In Compose werden UI-Elemente durch die zusammensetzbaren Funktionen dargestellt, die beim Aufrufen eine UI ausgeben. Diese 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 in seinem übergeordneten Element, das als Position (x, y) und Größe angegeben wird, die 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 schränken die minimalen und maximalen width
und height
eines Elements ein. Wenn ein Element untergeordnete Elemente hat, kann es zur Bestimmung seiner Größe jedes untergeordnete Element messen. Sobald ein Element seine eigene Größe bestimmt und meldet, kann es festlegen, wie seine untergeordneten Elemente relativ zu sich selbst platziert werden sollen. Dies wird unter Benutzerdefinierte Layouts erstellen ausführlich beschrieben.
Das Layout jedes Knotens in der Struktur der Benutzeroberfläche erfolgt in drei Schritten. Jeder Knoten muss:
- Untergeordnete Elemente messen
- Größe selbst festlegen
- Untergeordnete Elemente platzieren
Damit legen Sie fest, wann Sie Ihre Kinder messen und platzieren dürfen.
Das Messen eines Layouts kann nur während der Messung und des Layoutdurchlaufs erfolgen und ein untergeordnetes Element kann nur während der Layoutdurchläufe (und erst nach der Messung) platziert werden. Aufgrund von Compose-Bereichen wie MeasureScope
und PlacementScope
wird dies bei der Kompilierung erzwungen.
Layoutmodifikator verwenden
Mit dem layout
-Modifikator können Sie ändern, wie ein Element gemessen und angeordnet wird. Layout
ist eine Lambda-Funktion. Die Parameter enthalten das zu messende Element, 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 steuern. Genau dies geschieht mit dem 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 ist das gewünschte Verhalten, wenn der obere Abstand von Text
auf 24.dp
festgelegt wird:
Hier ist der Code zum Erstellen des 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 passiert 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 eine Lambda-Funktion für das Platzieren der zusammengefassten Elemente zurückgibt. In diesem Fall ist dies die Höhe zwischen der letzten Referenz und dem hinzugefügten oberen Abstand. - Platzieren Sie die umschlossenen Elemente auf dem Bildschirm, indem Sie
placeable.place(x, y)
aufrufen. Wenn die umschlossenen Elemente nicht platziert werden, sind sie nicht sichtbar. Die Positiony
entspricht dem oberen Abstand, also der Position der ersten Referenz des Textes.
Um zu prüfen, ob das wie erwartet funktioniert, verwenden Sie diesen Modifikator in einem 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 anordnen 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 Layout
-Funktion 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.
Mit 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 Layout
(ohne die Einschränkungen minHeight
) eingeschränkt und basierend auf dem yPosition
der vorherigen zusammensetzbaren Funktion platziert.
So wird diese 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!") } }
Layout-Richtung
Sie können die Layoutrichtung einer zusammensetzbaren Funktion ändern, indem Sie die Zusammensetzung von LocalLayoutDirection
lokal ändern.
Wenn Sie zusammensetzbare Funktionen manuell auf dem Bildschirm platzieren, ist das LayoutDirection
Teil der LayoutScope
des layout
-Modifikator oder der zusammensetzbaren Layout
.
Wenn Sie layoutDirection
verwenden, platzieren Sie die zusammensetzbaren Funktionen mit place
. Im Gegensatz zur Methode placeRelative
ändert sich place
nicht abhängig von der 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. Informationen zu benutzerdefinierten Layouts in Aktion finden Sie unter Beispiele zum Erstellen benutzerdefinierter Layouts erstellen.
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 „Layouts erstellen“
- Grafiken in „Compose“
- Modifikatoren zum Schreiben