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 Methoden verwendet:
- 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 zusammensetzbaren 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 eine Eingabe entgegen und generiert die Inhalte, die auf dem Bildschirm angezeigt werden. 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 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 platziert.
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
Rowwird aufgefordert, eine Messung vorzunehmen. - Der Stammknoten
Rowfordert sein erstes untergeordnetes ElementImageauf, die Messung durchzuführen. Imageist ein Blattknoten (d. h. er hat keine untergeordneten Elemente). Daher wird eine Größe gemeldet und es werden Placement-Anweisungen zurückgegeben.- Der Stammknoten
Rowfordert seinen zweiten untergeordneten KnotenColumnauf, 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
Columnfordert seinen zweiten untergeordneten KnotenTextauf, eine Messung durchzuführen. - Der zweite
Text-Knoten ist ein Blattknoten. Er gibt also eine Größe an und gibt Platzierungsanweisungen zurück. - Nachdem der Knoten
Columnseine untergeordneten Elemente gemessen, in der Größe angepasst und platziert hat, kann er seine eigene Größe und Platzierung bestimmen. - Nachdem der Stammknoten
Rowseine 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, ein ganzes 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: Intrinsic Measurements. 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.
clickablereagiert auf Nutzereingaben und zeigt einen Ripple-Effekt an.- Mit
paddingwird um ein Element herum Platz geschaffen. - Mit
fillMaxWidthwird festgelegt, dass das Composable die maximale Breite des übergeordneten Elements einnimmt. - 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-Funktion. 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