Mit Jetpack Compose lässt sich die Benutzeroberfläche Ihrer App viel einfacher gestalten und entwickeln. Compose wandelt den Status in UI-Elemente um. Dazu werden folgende Schritte ausgeführt:
- Zusammensetzung von Elementen
- Layout von Elementen
- Zeichnen von Elementen
In diesem Dokument geht es um das Layout von Elementen. Es werden einige der Bausteine erläutert, die Compose für das Layout von UI-Elementen bietet.
Ziele von Layouts in Compose
Die Jetpack Compose-Implementierung des Layoutsystems hat zwei Hauptziele:
- Hohe Leistung
- Einfaches Schreiben von benutzerdefinierten Layouts
Grundlagen von komponierbaren Funktionen
Composable-Funktionen sind der grundlegende Baustein von Compose. Eine zusammensetzbare Funktion ist eine Funktion, die Unit
ausgibt, das einen Teil Ihrer Benutzeroberfläche beschreibt. Die Funktion nimmt einige Eingaben entgegen und generiert, was auf dem Bildschirm angezeigt wird. Weitere Informationen zu Composables finden Sie in der Dokumentation zum Compose-Konzeptmodell.
Eine zusammensetzbare Funktion kann mehrere UI-Elemente ausgeben. Wenn Sie jedoch keine Anleitung dazu geben, wie sie angeordnet werden sollen, kann es sein, dass Compose die Elemente auf eine Weise anordnet, die Ihnen nicht gefällt. Mit diesem Code werden beispielsweise zwei Textelemente generiert:
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
Ohne Angaben dazu, wie die Elemente angeordnet werden sollen, stapelt Compose die Textelemente übereinander, sodass sie nicht lesbar sind:
Compose bietet eine Sammlung von gebrauchsfertigen Layouts, mit denen Sie Ihre UI-Elemente anordnen können. Außerdem lassen sich damit ganz einfach eigene, speziellere Layouts definieren.
Standardmäßige Layoutkomponenten
In vielen Fällen können Sie einfach die Standard-Layoutelemente 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") } }
Verwenden Sie Row
, um Elemente horizontal auf dem Bildschirm zu platzieren. Sowohl Column
als auch Row
unterstützen die Konfiguration der 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) } } }
Mit Box
können Sie Elemente übereinander platzieren. In Box
kann auch die Ausrichtung der darin enthaltenen Elemente konfiguriert werden.
@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 eine eigene zusammensetzbare Funktion schreiben, um diese Layouts in einem komplexeren Layout zu kombinieren, das zu Ihrer App passt.
Um die Position von untergeordneten Elementen in einem Row
festzulegen, verwenden Sie die Argumente horizontalArrangement
und verticalAlignment
. Legen Sie für ein 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 Durchgang angeordnet. Jeder Knoten wird zuerst aufgefordert, sich selbst zu messen, und dann alle untergeordneten Elemente rekursiv zu messen. Dabei werden Größenbeschränkungen im Baum an die untergeordneten Elemente weitergegeben. Anschließend werden die Blattknoten in der Größe angepasst und platziert. Die aufgelösten Größen und Platzierungsanweisungen werden dann wieder nach oben im Baum weitergegeben.
Kurz gesagt: Eltern werden vor ihren Kindern gemessen, aber nach ihnen in Größe und Position angepasst.
Betrachten Sie die folgende SearchResult
-Funktion.
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
Diese Funktion ergibt den folgenden UI-Baum.
SearchResult
Row
Image
Column
Text
Text
Im Beispiel SearchResult
folgt das Layout des UI-Baums dieser Reihenfolge:
- Der Stammknoten
Row
wird aufgefordert, eine Messung vorzunehmen. - Der Stammknoten
Row
fordert sein erstes untergeordnetes ElementImage
auf, die Messung durchzuführen. Image
ist ein Blattknoten (d. h. er hat keine untergeordneten Elemente). Daher wird eine Größe gemeldet und es werden Placement-Anweisungen zurückgegeben.- Der Stammknoten
Row
fordert seinen zweiten untergeordneten KnotenColumn
auf, die Messung durchzuführen. - Der
Column
-Knoten fordert sein erstesText
-untergeordnetes Element auf, eine Messung durchzuführen. - Der erste
Text
-Knoten ist ein Blattknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück. - Der Knoten
Column
fordert seinen zweiten untergeordneten KnotenText
auf, die Messung durchzuführen. - Der zweite
Text
-Knoten ist ein Blattknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück. - Nachdem der
Column
-Knoten seine untergeordneten Elemente gemessen, in der Größe angepasst und platziert hat, kann er seine eigene Größe und Platzierung bestimmen. - Nachdem der Stammknoten
Row
seine untergeordneten Elemente gemessen, in der Größe angepasst und platziert hat, kann er seine eigene Größe und Platzierung festlegen.
Leistung
Compose erzielt eine hohe Leistung, indem Kinder nur einmal gemessen werden. Die Single-Pass-Messung ist gut für die Leistung, da Compose tiefe UI-Bäume effizient verarbeiten kann. Wenn ein Element sein untergeordnetes Element zweimal gemessen hat und dieses untergeordnete Element jedes seiner untergeordneten Elemente zweimal gemessen hat usw., müsste bei einem einzelnen Versuch, das gesamte UI zu gestalten, viel Arbeit geleistet werden, was es schwierig macht, die Leistung Ihrer App aufrechtzuerhalten.
Wenn für Ihr Layout aus irgendeinem Grund mehrere Messungen erforderlich sind, bietet Compose ein spezielles System, intrinsische Messungen. Weitere Informationen zu dieser Funktion finden Sie hier.
Da Analyse und Platzierung separate Unterphasen des Layout-Durchlaufs sind, können Änderungen, die sich nur auf die Platzierung von Elementen und nicht auf die Analyse auswirken, separat ausgeführt werden.
Modifizierer in Layouts verwenden
Wie im Abschnitt Compose-Modifikatoren beschrieben, können Sie Modifikatoren verwenden, um Ihre Composables zu dekorieren oder zu erweitern. Modifikatoren sind für die Anpassung des Layouts unerlässlich. Hier werden beispielsweise mehrere Modifizierer 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 Modifikatorfunktionen zusammen verwendet.
clickable
reagiert auf Nutzereingaben und zeigt einen Ripple-Effekt an.- Mit
padding
wird um ein Element herum Platz geschaffen. - Mit
fillMaxWidth
wird festgelegt, dass das Composable die maximale Breite einnimmt, die ihm vom übergeordneten Element zugewiesen wird. - 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 Compose-Gesten.
Informationen zu Listen und Lazy Lists finden Sie in der Dokumentation zu Compose-Listen.
Responsive Layouts
Ein Layout sollte unter Berücksichtigung verschiedener Bildschirmausrichtungen und Formfaktoren entworfen werden. Compose bietet standardmäßig einige Mechanismen, mit denen Sie Ihre zusammensetzbaren Layouts an verschiedene Bildschirmkonfigurationen anpassen können.
Einschränkungen
Um die Einschränkungen des übergeordneten Elements zu kennen und das Layout entsprechend zu gestalten, können Sie ein BoxWithConstraints
verwenden. Die Messbeschränkungen finden Sie im Umfang der Content-Lambda. Mit diesen Messbeschränkungen können Sie verschiedene Layouts für unterschiedliche Bildschirmkonfigurationen erstellen:
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
Slotbasierte Layouts
Compose bietet eine Vielzahl von Composables, die auf Material Design basieren. Die androidx.compose.material:material
-Abhängigkeit (die beim Erstellen eines Compose-Projekts in Android Studio enthalten ist) erleichtert die Erstellung von Benutzeroberflächen. Elemente wie Drawer
, FloatingActionButton
und TopAppBar
sind alle vorhanden.
Material-Komponenten nutzen Slot-APIs, ein Muster, das in Compose eingeführt wurde, um Composables eine zusätzliche Anpassungsebene zu ermöglichen. Dieser Ansatz macht Komponenten flexibler, da sie ein untergeordnetes Element akzeptieren, das sich selbst konfigurieren kann, anstatt jeden Konfigurationsparameter des untergeordneten Elements verfügbar zu machen.
Durch Slots wird in der Benutzeroberfläche ein leerer Bereich geschaffen, den der Entwickler nach Belieben füllen kann. Hier sind die Slots, die Sie in einem TopAppBar
anpassen können:
Composables verwenden in der Regel eine content
-Composable-Lambda-Funktion ( content: @Composable
() -> Unit
). Slot-APIs stellen mehrere content
-Parameter für bestimmte Zwecke zur Verfügung.
Mit TopAppBar
können Sie beispielsweise die Inhalte 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
lässt sich ganz einfach prüfen, ob diese Komponenten richtig positioniert sind und korrekt zusammenarbeiten.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Empfehlungen für dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Modifizierer für „Verfassen“
- Kotlin für Jetpack Compose
- Material-Komponenten und ‑Layouts