Jetpack Compose vereinfacht das Entwerfen und Erstellen der Benutzeroberfläche Ihrer Anwendung. Compose wandelt den Status über einen der folgenden Schritte in UI-Elemente um:
- Zusammensetzung der Elemente
- Layout der Elemente
- Zeichnung von Elementen
In diesem Dokument wird das Layout von Elementen erläutert. Außerdem werden einige der Bausteine erläutert, die in der Funktion „Compose“ für das Layout Ihrer UI-Elemente verfügbar sind.
Ziele von Layouts in der Funktion "Compose"
Die Jetpack Compose-Implementierung des Layoutsystems hat zwei Hauptziele:
- Hohe Leistung
- Das Erstellen benutzerdefinierter Layouts ist ganz einfach.
Grundlagen zu zusammensetzbaren Funktionen
Zusammensetzbare Funktionen sind der grundlegende Baustein der Funktion „Compose“. Eine zusammensetzbare Funktion ist eine Funktion, die Unit
ausgibt und einen Teil Ihrer UI beschreibt. Die Funktion generiert einige Eingaben und generiert das, was auf dem Bildschirm angezeigt wird. Weitere Informationen zu zusammensetzbaren Funktionen finden Sie in der Dokumentation zum Meditativen Modell erstellen.
Eine zusammensetzbare Funktion kann mehrere UI-Elemente ausgeben. Wenn Sie jedoch keine Anleitung zur Anordnung nennen, können die Elemente in der Funktion „Compose“ auf unpassende Weise angeordnet werden. Mit diesem Code werden beispielsweise zwei Textelemente generiert:
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
Ohne Anleitung werden die Textelemente übereinander gestapelt, sodass sie unlesbar werden:
Compose bietet eine Sammlung gebrauchsfertiger Layouts, mit denen Sie Ihre UI-Elemente anordnen können. Außerdem können Sie damit ganz einfach eigene, spezifischere Layouts definieren.
Komponenten für das Standardlayout
In vielen Fällen können Sie einfach die Standard-Layoutelemente von Composer verwenden.
Mit Column
können Sie Elemente vertikal auf dem Bildschirm platzieren.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
Entsprechend kannst du Row
verwenden, 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 legen. Box
unterstützt auch die Konfiguration einer spezifischen 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 ausgefeilteren Layout zu kombinieren, das zu Ihrer App passt.
Wenn Sie die Position von Kindern in einem Row
festlegen möchten, verwenden Sie die Argumente horizontalArrangement
und verticalAlignment
. Legen Sie für 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 { /*...*/ } } }
Layoutmodell
Im Layoutmodell wird die UI-Struktur in einer einzelnen Karte bzw. einem einzelnen Ticket angelegt. Jeder Knoten wird zuerst dazu aufgefordert, sich selbst zu messen und dann alle untergeordneten Elemente rekursiv zu messen. Dabei werden Größeneinschränkungen des Baums an die untergeordneten Elemente weitergegeben. Anschließend werden die Blattknoten in der Größe angepasst und platziert, wobei die aufgelösten Größen und Platzierungsanweisungen an den Baum übergeben werden.
Kurz gesagt: Eltern messen vor ihren Kindern, werden aber entsprechend der Größe und nach den Kindern 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 SearchResult
-Beispiel folgt das Baumlayout der UI in dieser Reihenfolge:
- Der Stammknoten
Row
wird zu einer Messung aufgefordert. - Der Stammknoten
Row
bittet seinen ersten untergeordneten Knoten,Image
, zu messen. Image
ist ein Blattknoten, d. h., er hat keine untergeordneten Elemente. Daher wird eine Größe angegeben und eine Platzierungsanleitung zurückgegeben.- Der Stammknoten
Row
fordert seinen zweiten untergeordneten Knoten,Column
, die Messung an. - Der Knoten
Column
fordert seinen erstenText
-untergeordneten Knoten an, eine Messung durchzuführen. - Der erste
Text
-Knoten ist ein Blattknoten, daher meldet er eine Größe und gibt Anleitung zur Platzierung zurück. - Der Knoten
Column
fordert seinen zweitenText
-untergeordneten Knoten an, eine Messung durchzuführen. - Der zweite
Text
-Knoten ist ein Blattknoten, daher meldet er eine Größe und gibt Anleitung zur Platzierung zurück. - Nachdem der
Column
-Knoten nun seine untergeordneten Elemente gemessen, bemessen und platziert hat, kann er seine eigene Größe und Platzierung bestimmen. - Nachdem der Stammknoten
Row
nun seine untergeordneten Elemente gemessen, skaliert und platziert hat, kann er seine eigene Größe und Position bestimmen.
Leistung
Mit der Funktion „Compose“ lässt sich eine hohe Leistung erzielen, da Kinder nur einmal gemessen werden. Die Messung mit nur einem Durchlauf verbessert die Leistung und ermöglicht es Compose, tiefe UI-Bäume effizient zu verarbeiten. Wenn ein Element sein untergeordnetes Element zweimal gemessen hat und dieses Kind jedes seiner untergeordneten Elemente zweimal gemessen hat, wäre ein einziger Versuch, das Layout einer gesamten UI zu erstellen, viel Arbeit erfordern, was die Leistung der App erschweren würde.
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 unter Intrinsische Messungen in Compose-Layouts.
Da Messung und Platzierung unterschiedliche Teilphasen des Layoutpasses sind, können alle Änderungen, die sich nur auf die Platzierung der Elemente und nicht auf die Messung auswirken, separat ausgeführt werden.
Modifikatoren in Layouts verwenden
Wie im Abschnitt Modifikatoren zum Verfassen beschrieben, können Sie Ihre zusammensetzbaren Funktionen mit Modifikatoren gestalten oder erweitern. Modifikatoren sind wichtig,
um Ihr Layout anzupassen. Hier verketten wir beispielsweise mehrere Modifikatoren, um 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), ) { /*...*/ } } }
Beachten Sie, dass im obigen Code verschiedene Modifikatorfunktionen zusammen verwendet werden.
clickable
erstellt eine zusammensetzbare Reaktion auf Nutzereingabe und zeigt eine Welle.padding
fügt Raum um ein Element hinzu.- Mit
fillMaxWidth
füllt die zusammensetzbare Funktion die maximale Breite aus, die ihr von ihrem übergeordneten Element vorgegeben wird. size()
gibt die bevorzugte Breite und Höhe eines Elements an.
Scrollbare Layouts
Weitere Informationen zu scrollbaren Layouts finden Sie in der Dokumentation zu Schreibbewegungen.
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 und Formfaktorgrößen entworfen werden. Compose bietet vorkonfigurierte Mechanismen, mit denen Sie Ihre zusammensetzbaren Layouts an verschiedene Bildschirmkonfigurationen anpassen können.
Einschränkungen
Sie können BoxWithConstraints
verwenden, um die Einschränkungen der übergeordneten Ressource zu kennen und das Layout entsprechend zu entwerfen. Die Einschränkungen für die Messung sind im Bereich der inhaltsbezogenen Lambda-Funktion zu finden. Mit diesen Einschränkungen für Messungen 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 von zusammensetzbaren Funktionen, die auf Material Design mit der Abhängigkeit androidx.compose.material:material
basieren (die beim Erstellen eines Composer-Projekts in Android Studio enthalten ist), um das Erstellen einer UI zu vereinfachen. Elemente wie Drawer
, FloatingActionButton
und TopAppBar
sind alle vorhanden.
Für Materialkomponenten werden in großem Umfang Slot-APIs genutzt. Mit dem in der Funktion „Compose“ eingeführten Muster lassen sich zusammensetzbare Funktionen noch individueller gestalten. Auf diese Weise sind die Komponenten flexibler, da sie ein untergeordnetes Element akzeptieren, das sich selbst konfigurieren kann, anstatt jeden Konfigurationsparameter des untergeordneten Elements verfügbar zu machen.
Slots hinterlassen in der Benutzeroberfläche einen leeren Bereich, den der Entwickler nach Belieben füllen kann. Sie können beispielsweise die folgenden Slots in einem TopAppBar
anpassen:
Zusammensetzbare Funktionen verwenden in der Regel eine zusammensetzbare content
-Lambda-Funktion ( content: @Composable
() -> Unit
). Slot-APIs stellen mehrere content
-Parameter für bestimmte Anwendungsfälle bereit.
Mit TopAppBar
können Sie beispielsweise die Inhalte für title
, navigationIcon
und actions
bereitstellen.
Mit Scaffold
kannst du beispielsweise eine UI mit der grundlegenden Material Design-Layoutstruktur implementieren. Scaffold
Es bietet Slots für die gängigsten Material-Komponenten der obersten Ebene, z. B. TopAppBar
, BottomAppBar
, FloatingActionButton
und Drawer
. Mit Scaffold
kann ganz einfach sichergestellt werden, dass diese Komponenten richtig positioniert sind und richtig zusammenwirken.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Modifikatoren zum Verfassen
- Kotlin für Jetpack Compose
- Materialkomponenten und Layouts