In Compose werden UI-Elemente durch zusammensetzbare Funktionen dargestellt, die beim Aufrufen 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, angegeben als (x, y)-Position und Größe, angegeben als width
und height
.
Übergeordnete Elemente definieren die Einschränkungen für ihre untergeordneten Elemente. Die Größe eines Elements muss innerhalb dieser Einschränkungen definiert werden. Mit Einschränkungen werden die Mindest- und Höchstwerte width
und height
eines Elements begrenzt. Wenn ein Element untergeordnete Elemente hat, wird möglicherweise jedes untergeordnete Element gemessen, um die Größe zu bestimmen. Sobald ein Element seine eigene Größe ermittelt und gemeldet hat, kann es festlegen, wie seine untergeordneten Elemente relativ zu ihm platziert werden sollen. Weitere Informationen finden Sie unter Benutzerdefinierte Layouts erstellen.
Die Anordnung der einzelnen Knoten im UI-Baum erfolgt in drei Schritten. Jeder Knoten muss:
- Untergeordnete Elemente messen
- Eigene Größe festlegen
- Untergeordnete Elemente platzieren
Mithilfe von Bereichen wird festgelegt, wann Sie Ihre untergeordneten Elemente messen und platzieren können.
Ein Layout kann nur während der Mess- und Layoutdurchläufe gemessen werden. Ein untergeordnetes Element kann nur während der Layoutdurchläufe platziert werden (und nur, nachdem es gemessen wurde). Aufgrund von Compose-Bereichen wie MeasureScope
und PlacementScope
wird dies zur Kompilierungszeit erzwungen.
Layout-Modifikator verwenden
Mit dem Modifikator layout
können Sie ändern, wie ein Element gemessen und angeordnet wird. Layout
ist ein Lambda; seine Parameter umfassen das Element, das Sie messen können, übergeben als measurable
, und die eingehenden Einschränkungen dieses Composeables, übergeben als constraints
. Ein benutzerdefinierter Layout-Modifikator kann so aussehen:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Zeigen wir ein Text
auf dem Bildschirm an und steuern den Abstand von der Oberkante zur Grundlinie der ersten Textzeile. Genau das macht der Modifikator paddingFromBaseline
. Wir implementieren ihn hier als Beispiel.
Dazu platzieren Sie das Composeable manuell auf dem Bildschirm, indem Sie die Taste layout
gedrückt halten. Hier ist das gewünschte Verhalten, wenn das obere Text
-Abstand 24.dp
festgelegt ist:
Hier ist der Code, mit dem dieses Spacing erzeugt wird:
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) } }
Hier ist, was in diesem Code passiert:
- Im Lambda-Parameter
measurable
wird derText
, der durch den messbaren Parameter dargestellt wird, durch Aufrufen vonmeasurable.measure(constraints)
gemessen. - Sie geben die Größe des Composeables an, indem Sie die Methode
layout(width, height)
aufrufen. Dadurch wird auch ein Lambda-Ausdruck zurückgegeben, der zum Platzieren der umhüllten Elemente verwendet wird. In diesem Fall ist es die Höhe zwischen der letzten Grundlinie und dem hinzugefügten oberen Abstand. - Sie positionieren die umgebrochenen Elemente auf dem Bildschirm, indem Sie
placeable.place(x, y)
aufrufen. Wenn die umhüllten Elemente nicht platziert werden, sind sie nicht sichtbar. Diey
-Position entspricht dem oberen Abstand, also der Position der ersten Textgrundlinie.
Verwenden Sie diesen Modifikator für Text
, um zu prüfen, ob dies 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)) } }
Benutzerdefinierte Layouts erstellen
Der Modifizierer layout
ändert nur das Anruf-Composeable. Wenn Sie mehrere Elemente messen und ein Layout dafür erstellen möchten, verwenden Sie stattdessen das Element Layout
. Mit diesem Composeable können Sie untergeordnete Elemente manuell messen und anordnen. Alle Layouts der höheren Ebenen wie Column
und Row
werden mit dem Layout
-Kompositelement 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 Modifikator layout
ist measurables
die Liste der untergeordneten Elemente, die gemessen werden sollen, und constraints
sind die Einschränkungen des übergeordneten Elements.
Gemäß der gleichen 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 Composeables sind durch die Layout
-Einschränkungen (ohne die minHeight
-Einschränkungen) eingeschränkt und werden basierend auf der yPosition
des vorherigen Composeables platziert.
So wird das benutzerdefinierte Composed-Element 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
Ändern Sie die Layoutrichtung eines Composeables, indem Sie die LocalLayoutDirection
-Komposition lokal ändern.
Wenn Sie Zusammensetzbare manuell auf dem Bildschirm platzieren, ist LayoutDirection
Teil der LayoutScope
des layout
- oder Layout
-Modifikators.
Wenn du layoutDirection
verwendest, platziere die Elemente mit place
. Im Gegensatz zur Methode placeRelative
ändert sich place
nicht je nach Layoutrichtung (links nach rechts oder rechts nach links).
Benutzerdefinierte Layouts in der Praxis
Weitere Informationen zu Layouts und Modifikatoren finden Sie unter Grundlegende Layouts in Compose. In den Beispielen für benutzerdefinierte Layouts in Compose können Sie sich benutzerdefinierte Layouts in Aktion ansehen.
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 Maße in Compose-Layouts
- Grafiken in Compose
- Modifizierer erstellen