Mit Jetpack Compose können Sie die Benutzeroberfläche Ihrer App viel einfacher entwerfen und erstellen. Composewandelt den Status über folgende Methoden in UI-Elemente um:
- Zusammensetzung der Elemente
- Layout der Elemente
- Zeichnen von Elementen
In diesem Dokument geht es hauptsächlich um das Layout von Elementen. Es werden einige der Bausteine von Compose erläutert, mit denen Sie Ihre UI-Elemente layouten können.
Ziele von Layouts in Compose
Die Jetpack Compose-Implementierung des Layoutsystems hat zwei Hauptziele:
- Hohe Leistung
- Möglichkeit, ganz einfach benutzerdefinierte Layouts zu erstellen
Grundlagen komponierbarer Funktionen
Kompositionsfähige Funktionen sind der grundlegende Baustein von Compose. Eine kombinierbare Funktion ist eine Funktion, die Unit
ausgibt und einen Teil Ihrer Benutzeroberfläche 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 kombinierbare Funktion kann mehrere UI-Elemente ausgeben. Wenn Sie jedoch keine Vorgaben dazu machen, wie sie angeordnet werden sollen, ordnet Compose die Elemente möglicherweise so an, wie Sie es nicht möchten. Mit diesem Code werden beispielsweise zwei Textelemente generiert:
@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:
Compose bietet eine Sammlung von vorgefertigten Layouts, mit denen Sie Ihre UI-Elemente anordnen können. Außerdem können Sie damit ganz einfach eigene, speziellere Layouts definieren.
Standardlayoutkomponenten
In vielen Fällen können Sie einfach die Standardlayoutelemente von Compose verwenden.
Mit Column
können Sie Elemente vertikal auf dem Bildschirm platzieren.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
Mit Row
können Sie Elemente horizontal auf dem Bildschirm platzieren. Sowohl Column
als auch Row
unterstützen die Konfiguration der Ausrichtung der 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) } } }
Mit Box
kannst du Elemente übereinander legen. 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") } }
Oft sind diese Bausteine alles, was Sie brauchen. Sie können Ihre eigene zusammensetzbare Funktion schreiben, um diese Layouts zu einem komplexeren Layout zu kombinieren, das zu Ihrer App passt.
Um die Position von untergeordneten Elementen innerhalb einer Row
festzulegen, legen Sie die Argumente horizontalArrangement
und verticalAlignment
fest. Legen Sie für eine Column
die Argumente verticalArrangement
und horizontalAlignment
fest:
@Composable fun ArtistCardArrangement(artist: Artist) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { /*...*/ } } }
Das Layoutmodell
Im Layoutmodell wird der UI-Baum in einem einzigen Durchlauf dargestellt. Jeder Knoten wird zuerst auf seine Größe geprüft und dann werden alle untergeordneten Knoten rekursiv gemessen. Dabei werden die Größenbeschränkungen an die untergeordneten Knoten im Baum weitergeleitet. Anschließend werden die Blätter dimensioniert und platziert. Die ermittelten Größen und Platzierungsanweisungen werden zurück zum Stamm des Baums übergeben.
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:
- Der Stammknoten
Row
soll gemessen werden. - Der Stammknoten
Row
bittet sein erstes untergeordnetes Element,Image
, um eine Messung. Image
ist ein Endknoten (d. h., er hat keine untergeordneten Elemente). Daher wird eine Größe angegeben und Platzierungsanweisungen zurückgegeben.- Der Stammknoten
Row
bittet sein zweites Kind,Column
, um eine Messung. - Der
Column
-Knoten bittet sein erstesText
-untergeordnetes Element, eine Messung durchzuführen. - Der erste
Text
-Knoten ist ein Blattknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück. - Der
Column
-Knoten bittet sein zweitesText
-Kind um eine Messung. - Der zweite
Text
-Knoten ist ein Endknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück. - Nachdem der Knoten
Column
seine untergeordneten Elemente gemessen, ihre Größe festgelegt und platziert hat, kann er seine eigene Größe und Platzierung bestimmen. - Nachdem der Stammknoten
Row
seine untergeordneten Knoten gemessen, ihre Größe festgelegt und platziert hat, kann er seine eigene Größe und Platzierung bestimmen.
Leistung
Compose erreicht eine hohe Leistung, da untergeordnete Elemente nur einmal gemessen werden. Die Messung mit nur einem Durchlauf ist leistungsstark 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 Ihr Layout aus irgendeinem Grund mehrere Messungen erfordert, bietet Compose ein spezielles System: intrinsische Messungen. Weitere Informationen zu dieser Funktion finden Sie unter Intrinsische Maße 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 Modifizierer zusammenstellen erläutert, können Sie Modifizierer verwenden, um Ihre Composeables zu verzieren oder zu ergänzen. Modifikatoren sind unerlässlich, um Ihr Layout anzupassen. Hier werden beispielsweise mehrere Modifikatoren verkettet, um die ArtistCard
anzupassen:
@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), ) { /*...*/ } } }
Im obigen Code werden verschiedene Modifiziererfunktionen zusammen verwendet.
- Mit
clickable
reagiert ein Composeable auf Nutzereingaben und zeigt eine Welle an. padding
fügt einem Element einen Abstand hinzu.- Mit
fillMaxWidth
wird das zusammensetzbare Element auf die maximale Breite des übergeordneten Elements eingestellt. - Mit
size()
wird die bevorzugte Breite und Höhe eines Elements angegeben.
Scrollbare Layouts
Weitere Informationen zu scrollbaren Layouts finden Sie in der Dokumentation zu Eingabegesten.
Weitere Informationen zu Listen und Lazy-Listen finden Sie in der Dokumentation zum Erstellen von Listen.
Responsive Layouts
Ein Layout sollte so gestaltet sein, dass es für verschiedene Bildschirmausrichtungen und Formfaktoren geeignet ist. Compose bietet standardmäßig einige Mechanismen, mit denen sich Ihre zusammensetzbaren Layouts an verschiedene Bildschirmkonfigurationen anpassen lassen.
Einschränkungen
Um die Einschränkungen des übergeordneten Elements zu kennen und das Layout entsprechend zu gestalten, können Sie eine BoxWithConstraints
verwenden. Die Messeinschränkungen finden Sie im Bereich der Content-Lambda. Anhand dieser Maßbeschränkungen können Sie verschiedene Layouts für verschiedene Bildschirmkonfigurationen erstellen:
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
Slotbasierte 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 verfügbar.
Materialkomponenten nutzen häufig Steckplatz-APIs, ein Muster, das in Compose eingeführt wurde, um eine Anpassungsebene auf Composables anzuwenden. Dieser Ansatz macht Komponenten flexibler, da sie ein untergeordnetes Element akzeptieren, das sich selbst konfigurieren kann, anstatt jeden Konfigurationsparameter des untergeordneten Elements offenlegen zu müssen.
Slots lassen einen leeren Bereich in der Benutzeroberfläche, den der Entwickler nach Belieben füllen kann. In einem TopAppBar
können Sie beispielsweise die folgenden Slots anpassen:
Für Composables wird in der Regel ein content
-komposables Lambda ( content: @Composable
() -> Unit
) verwendet. Slot-APIs stellen für bestimmte Verwendungen mehrere content
-Parameter bereit.
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
. Mit Scaffold
können Sie ganz einfach dafür sorgen, dass diese Komponenten richtig positioniert sind und zusammen funktionieren.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Modifizierer erstellen
- Kotlin für Jetpack Compose
- Materialkomponenten und -layouts