Grundlagen zum Verfassen von Layouts

Mit Jetpack Compose können Sie die Benutzeroberfläche Ihrer App viel einfacher entwerfen und erstellen. Verfassen wandelt den Zustand in UI-Elemente um, und zwar über:

  1. Zusammensetzung der Elemente
  2. Layout von Elementen
  3. Zeichnung von Elementen

Transformierenden Status über Komposition, Layout und Zeichnung in die Benutzeroberfläche einbinden

In diesem Dokument geht es um das Layout von Elementen und erklärt einige Gebäude Blocks Compose bietet Ihnen die Möglichkeit, Ihre UI-Elemente anzuordnen.

Ziele von Layouts in Compose

Die Jetpack Compose-Implementierung des Layoutsystems hat zwei Hauptziele:

Grundlagen komponierbarer Funktionen

Zusammensetzbare Funktionen sind der Grundbaustein von Compose. Eine zusammensetzbare Funktion ist eine Funktion, die Unit ausgibt und einen Teil Ihrer UI beschreibt. Die Funktion nimmt eine Eingabe entgegen und generiert die Inhalte, die auf dem Bildschirm angezeigt werden. Weitere Informationen zu Composeable-Modellen finden Sie in der Dokumentation Ein mentales Modell erstellen.

Eine zusammensetzbare Funktion kann mehrere UI-Elemente ausgeben. Wenn Sie jedoch keine wie sie angeordnet sein sollten, kann die Funktion „Schreiben“ Elemente auf eine Art und Weise an, die Ihnen nicht gefällt. Dieser Code generiert zum Beispiel Elemente:

@Composable
fun ArtistCard() {
    Text("Alfred Sisley")
    Text("3 minutes ago")
}

Ohne Angabe der gewünschten Anordnung stapelt Compose die Textelemente übereinander, sodass sie unlesbar werden:

Zwei Textelemente, die übereinander liegen und den Text unleserlich machen

Die Funktion „Compose“ bietet eine Reihe von einsatzbereiten Layouts, mit denen Sie Ihre UI-Elementen und erleichtert die Definition Ihrer eigenen, spezialisierteren Layouts.

Standardlayoutkomponenten

In vielen Fällen können Sie einfach das Standardlayout von Google Composer verwenden Elemente.

Verwenden Sie Column um Elemente vertikal auf dem Bildschirm zu platzieren.

@Composable
fun ArtistCardColumn() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

Zwei Textelemente, die in einem Spaltenlayout angeordnet sind, damit der Text gut lesbar ist

Verwenden Sie ebenso Row um Elemente horizontal auf dem Bildschirm zu platzieren. Unterstützung von Column und Row und konfigurieren die Ausrichtung der darin enthaltenen Elemente.

@Composable
fun ArtistCardRow(artist: Artist) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column {
            Text(artist.name)
            Text(artist.lastSeenOnline)
        }
    }
}

Ein komplexeres Layout mit einer kleinen Grafik neben einer Spalte mit Textelementen

Mit Box kannst du Elemente übereinander platzieren. Box unterstützt auch die Konfiguration einer bestimmten Ausrichtung der darin enthaltenen Elemente.

@Composable
fun ArtistAvatar(artist: Artist) {
    Box {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Icon(Icons.Filled.Check, contentDescription = "Check mark")
    }
}

Zwei übereinander gestapelte Elemente

Oft sind diese Bausteine alles, was Sie brauchen. Sie können Ihre eigene zusammensetzbare Funktion schreiben, um diese Layouts zu einem ausgefeilteren Layout zu kombinieren, das zu Ihrer App passt.

Vergleicht drei zusammensetzbare Funktionen des einfachen Layouts: Spalte, Zeile und Feld

Um die Position der untergeordneten Elemente innerhalb eines Row festzulegen, legen Sie horizontalArrangement und verticalAlignment Argumente. Legen Sie für ein Column-Objekt verticalArrangement und horizontalAlignment Argumente:

@Composable
fun ArtistCardArrangement(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column { /*...*/ }
    }
}

Elemente sind rechtsbündig ausgerichtet

Layoutmodell

Im Layoutmodell wird der UI-Baum in einem einzigen Durchlauf dargestellt. Jeder Knoten ist gebeten, sich selbst zu messen, dann alle untergeordneten Elemente rekursiv messen, Größenbeschränkungen in der Baumstruktur auf untergeordnete Elemente. Dann werden die Blattknoten platziert, wobei die festgelegten Größen und Platzierungsanweisungen an die Baum.

Kurz gesagt: Eltern werden vor ihren Kindern gemessen, aber nach ihren Kindern ausgewählt und platziert.

Betrachten Sie die folgende SearchResult-Funktion.

@Composable
fun SearchResult() {
    Row {
        Image(
            // ...
        )
        Column {
            Text(
                // ...
            )
            Text(
                // ...
            )
        }
    }
}

Diese Funktion liefert den folgenden UI-Baum.

SearchResult
  Row
    Image
    Column
      Text
      Text

Im Beispiel SearchResult folgt das UI-Baumlayout dieser Reihenfolge:

  1. Der Stammknoten Row wird zum Messen aufgefordert.
  2. Der Stammknoten Row fordert die Messung durch sein erstes untergeordnetes Element, Image, an.
  3. Image ist ein Blattknoten (d. h., er hat keine untergeordneten Elemente), also gibt er eine Größe an. und gibt Anweisungen zur Platzierung zurück.
  4. Der Stammknoten Row bittet sein zweites Kind, Column, um eine Messung.
  5. Der Column-Knoten bittet sein erstes Text-untergeordnetes Element, eine Messung durchzuführen.
  6. Der erste Text-Knoten ist ein Blattknoten, also gibt er eine Größe an und gibt Anweisungen zur Platzierung.
  7. Der Column-Knoten fordert die Messung seines zweiten untergeordneten Text-Elements an.
  8. Der zweite Text-Knoten ist ein Endknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück.
  9. Nachdem der Column-Knoten nun seine untergeordneten Elemente gemessen, skaliert und platziert hat, eigene Größe und Platzierung bestimmen kann.
  10. Nachdem der Stammknoten Row seine untergeordneten Elemente gemessen, die Größe angepasst und platziert hat, eigene Größe und Platzierung bestimmen kann.

Reihenfolge von Messwerten, Größe und Platzierung im UI-Baum der Suchergebnisse

Leistung

Compose erreicht eine hohe Leistung, da untergeordnete Elemente nur einmal gemessen werden. Die Messung mit nur einem Durchlauf ist leistungsfördernd und ermöglicht es Compose, tiefe UI-Bäume effizient zu verarbeiten. Wenn ein Element sein untergeordnetes Element zweimal misst und dieses untergeordnete Element jedes seiner untergeordneten Elemente zweimal misst usw., ist für das Layout einer gesamten Benutzeroberfläche viel Arbeit erforderlich, was die Leistung Ihrer App beeinträchtigt.

Wenn für Ihr Layout aus irgendeinem Grund mehrere Messungen erforderlich sind, bietet die Funktion „Schreiben“ ein spezielles System, intrinsische Messungen. Weitere Informationen zu dieser Funktion in Intrinsische Messungen in Compose Layouts

Da Analyse und Platzierung unterschiedliche Teilphasen des Layout-Passes sind, können alle Änderungen, die sich nur auf das Platzieren von Elementen und nicht auf die Analyse auswirken, separat ausgeführt werden.

Modifikatoren in Layouts verwenden

Wie im Abschnitt Modifier zusammenstellen erläutert, können Sie Modifier verwenden, um Ihre Composeables zu verzieren oder zu ergänzen. Modifikatoren sind unerlässlich, um Ihr Layout anzupassen. Hier verketten wir beispielsweise mehrere Modifikatoren, zum Anpassen von ArtistCard:

@Composable
fun ArtistCardModifiers(
    artist: Artist,
    onClick: () -> Unit
) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ }
        Spacer(Modifier.size(padding))
        Card(
            elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        ) { /*...*/ }
    }
}

Ein noch komplexeres Layout, bei dem mithilfe von Modifikatoren die Anordnung der Grafiken und die Bereiche, in denen auf Nutzereingaben reagiert wird, geändert werden.

Im obigen Code werden verschiedene Modifikatorfunktionen zusammen verwendet.

  • Mit clickable reagiert ein Composeable auf Nutzereingaben und zeigt eine Welle an.
  • padding platziert ein Element mit Platz.
  • Mit fillMaxWidth wird für die zusammensetzbare Füllung die maximale Breite festgelegt, die von in das übergeordnete Element ein.
  • Mit size() wird die bevorzugte Breite und Höhe eines Elements angegeben.

Scrollbare Layouts

Weitere Informationen zu scrollbaren Layouts finden Sie in der Dokumentation zum Schreiben von Touch-Gesten

Weitere Informationen zu Listen und Lazy-Listen finden Sie in der Dokumentation zum Erstellen von Listen.

Responsive Layouts

Ein Layout sollte unter Berücksichtigung verschiedener Bildschirmausrichtungen entworfen werden. und Formfaktorgrößen. Compose bietet sofort ein paar Mechanismen, um die Anpassung Ihrer zusammensetzbaren Layouts an verschiedene Bildschirmkonfigurationen zu erleichtern.

Einschränkungen

Um die Einschränkungen des übergeordneten Elements zu kennen, und um das Layout können Sie einen BoxWithConstraints verwenden. Die Messeinschränkungen finden Sie im Bereich der Inhaltslambda. Mit diesen Messwerten können Sie Einschränkungen beim Erstellen verschiedener Layouts für unterschiedliche Bildschirmkonfigurationen:

@Composable
fun WithConstraintsComposable() {
    BoxWithConstraints {
        Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
    }
}

Anzeigenflächenbasierte Layouts

Compose bietet eine große Auswahl an Material Design-basierten Compose-Elementen mit der Abhängigkeit androidx.compose.material:material, die beim Erstellen eines Compose-Projekts in Android Studio enthalten ist. So lässt sich die Benutzeroberfläche ganz einfach erstellen. Elemente wie Drawer, FloatingActionButton, und TopAppBar sind alle angegeben.

Materialkomponenten nutzen in großem Umfang Slot-APIs. um über die zusammensetzbaren Funktionen Anpassungen hinzuzufügen. Dieser Ansatz sorgt dafür, Komponenten sind flexibler, da sie ein untergeordnetes Element akzeptieren, das anstatt jeden Konfigurationsparameter des untergeordneten Elements offenlegen zu müssen. Anzeigenflächen lassen einen leeren Bereich auf der Benutzeroberfläche, den der Entwickler nach Bedarf füllen kann. Für Dies sind z. B. die Anzeigenflächen, die Sie in einem TopAppBar:

Ein Diagramm, das die verfügbaren Slots in der App-Leiste „Material Components“ zeigt

Zusammensetzbare Elemente verwenden normalerweise ein zusammensetzbares content-Lambda ( content: @Composable () -> Unit). Slot-APIs stellen mehrere content-Parameter für bestimmte Anwendungsfälle zur Verfügung. Mit TopAppBar können Sie beispielsweise den Inhalt für title, navigationIcon und actions bereitstellen.

Mit Scaffold können Sie beispielsweise eine Benutzeroberfläche mit der grundlegenden Material Design-Layoutstruktur implementieren. Scaffold bietet Slots für die gängigsten Material-Komponenten der obersten Ebene, z. B. TopAppBar, BottomAppBar, FloatingActionButton und Drawer. Durch die Verwendung von Scaffold, kann ganz einfach überprüft werden, ob diese Komponenten richtig positioniert und zusammenarbeiten.

Die Beispiel-App „JetNews“, die mithilfe von Scaffold mehrere Elemente positioniert

@Composable
fun HomeScreen(/*...*/) {
    ModalNavigationDrawer(drawerContent = { /* ... */ }) {
        Scaffold(
            topBar = { /*...*/ }
        ) { contentPadding ->
            // ...
        }
    }
}

Derzeit liegen keine Empfehlungen vor.

Versuchen Sie, sich bei Ihrem Google-Konto .