Benutzerdefinierte Layouts

In Compose werden UI-Elemente durch die zusammensetzbaren Funktionen dargestellt, die einen UI-Element, das beim Aufruf zu einem UI-Baum hinzugefügt wird, der auf auf dem Bildschirm. Jedes UI-Element hat ein übergeordnetes Element und möglicherweise viele untergeordnete Elemente. Jedes -Element befindet sich ebenfalls innerhalb des übergeordneten Elements, das als Position (x, y) angegeben wird, und eine Größe, angegeben als width und height.

Übergeordnete Elemente definieren die Einschränkungen für ihre untergeordneten Elemente. Ein Element wird gebeten, um die Größe innerhalb dieser Einschränkungen zu definieren. Einschränkungen schränken die Mindest- und Maximal width und height eines Elements. Hat ein Element untergeordnete Elemente, kann es kann jedes untergeordnete Element messen, um seine Größe zu bestimmen. Sobald ein Element bestimmt, und meldet ihre eigene Größe, kann sie festlegen, wie ihr untergeordnete -Elemente relativ zu sich selbst, wie unter Benutzerdefinierte Layouts

Das Layout jedes Knotens in der Struktur der Benutzeroberfläche erfolgt in drei Schritten. Jeder Knoten muss:

  1. Untergeordnete Elemente messen
  2. Größe selbst festlegen
  3. Untergeordnete Elemente platzieren

Drei Schritte des Knotenlayouts: untergeordnete Elemente messen, Größe 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 Layout-Durchlaufs erfolgen. und ein untergeordnetes Element kann nur während des Layout-Passes platziert werden (und erst nachdem es gemessen). Aufgrund von Compose-Bereichen wie MeasureScope, und PlacementScope, bei der Kompilierung erzwungen.

Layoutmodifikator verwenden

Mit dem layout-Modifikator können Sie ändern, wie ein Element gemessen und platziert wird. aus. Layout ist Lambda; enthalten die Parameter das messbare Element, übergeben als measurable und die eingehenden Einschränkungen dieser zusammensetzbaren Funktion werden als constraints Ein benutzerdefinierter Layoutmodifikator kann so aussehen:

fun Modifier.customLayoutModifier() =
    layout { measurable, constraints ->
        // ...
    }

Zeige nun ein Text auf dem Bildschirm an und lege den Abstand von oben die Grundlinie der ersten Textzeile. Genau das ist der Der paddingFromBaseline-Modifikator wird hier als Beispiel implementiert. Verwenden Sie dazu den layout-Modifikator, um die zusammensetzbare Funktion manuell im Bildschirm. Hier ist das gewünschte Verhalten, wenn der obere Abstand von Text auf 24.dp festgelegt wird:

Zeigt den Unterschied zwischen dem normalen UI-Padding, das den Abstand zwischen den Elementen festlegt, und dem Text-Padding, durch den der Abstand von einer Referenz zur nächsten 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:

  1. Im Lambda-Parameter measurable messen Sie die Text, die durch den messbaren Parameter durch Aufrufen von measurable.measure(constraints).
  2. Sie geben die Größe der zusammensetzbaren Funktion an, indem Sie layout(width, height) aufrufen. , die auch eine Lambda-Funktion für das Platzieren der umschlossenen Elemente liefert. In in diesem Fall die Höhe zwischen der letzten Referenz und dem hinzugefügten oberen Abstand.
  3. Sie positionieren die umschlossenen Elemente auf dem Bildschirm, indem Sie placeable.place(x, y) Wenn die umschlossenen Elemente nicht platziert werden, werden sie nicht sichtbar sind. Die Position y entspricht dem oberen Abstand, also der Position die erste Grundlinie 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))
    }
}

Mehrere Vorschauen von Textelementen eines für den normalen Abstand zwischen den Elementen, das andere das Padding von einer Referenz zur nächsten

Benutzerdefinierte Layouts erstellen

Der layout-Modifikator ändert nur die aufrufende zusammensetzbare Funktion. Zum Messen und Layout mehreren zusammensetzbaren Funktionen verwenden, verwenden Sie stattdessen die zusammensetzbare Funktion Layout. Diese zusammensetzbare Funktion können Sie Kinder manuell messen und anordnen. Alle übergeordneten Layouts Column und Row werden mit der zusammensetzbaren Funktion Layout erstellt.

Erstellen wir eine sehr einfache Version von Column. Bei den meisten benutzerdefinierten Layouts 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 der gleichen Logik wie zuvor kann MyBasicColumn so implementiert werden: dies:

@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 eingeschränkt (ohne die minHeight), und sie werden basierend auf den yPosition der der vorherigen zusammensetzbaren Funktion.

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!")
    }
}

Mehrere Textelemente in einer Spalte übereinander gestapelt.

Layout-Richtung

Sie können die Layoutrichtung einer zusammensetzbaren Funktion ändern, indem Sie die LocalLayoutDirection-Komposition (lokal).

Wenn Sie zusammensetzbare Funktionen manuell auf dem Bildschirm platzieren, wird der LayoutDirection Teil des LayoutScope des layout-Modifikators oder der zusammensetzbaren Layout-Funktion.

Wenn Sie layoutDirection verwenden, platzieren Sie die zusammensetzbaren Funktionen mit place. Im Gegensatz zur placeRelative place ändert sich nicht je nach Layout-Richtung (von links nach rechts oder von rechts nach links).

Benutzerdefinierte Layouts in Aktion

Weitere Informationen zu Layouts und Modifikatoren finden Sie in der Grundlegende Layouts in Compose und benutzerdefinierte Layouts in der Beispiele zum Erstellen benutzerdefinierter Layouts erstellen

Weitere Informationen

Weitere Informationen zu benutzerdefinierten Layouts in Compose finden Sie in den folgenden zusätzlichen Ressourcen.

Videos