Sie können eine Grid-Containerkonfiguration definieren, um flexible Layouts zu erstellen, die auf verschiedene Bildschirmgrößen und Inhaltstypen reagieren. Auf dieser Seite wird Folgendes beschrieben:
- Raster definieren: Grundstruktur aus Zeilen und Spalten einrichten
- Elemente in einem Raster platzieren: Informationen dazu, wie Elemente in Rasterzellen platziert werden und wie Sie die Flussrichtung ändern
- Track-Größen verwalten: Feste, prozentuale, flexible und intrinsische Größen verwenden, um Track-Größen festzulegen
- Abstände festlegen: „Abstände“ zwischen Zeilen und Spalten verwalten
Raster definieren
Ein Raster besteht aus Spalten und Zeilen.
Die Grid zusammensetzbare Funktion hat einen config-Parameter
, der eine Lambda-Funktion akzeptiert, um die Spalten und Zeilen
in GridConfigurationScope zu definieren.
Im folgenden Beispiel wird ein Raster mit drei Zeilen und zwei Spalten definiert,
wobei jede eine feste Größe in Dp hat:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { }
Elemente in einem Raster platzieren
Grid verwendet die UI-Elemente in der content-Lambda-Funktion und platziert sie in Rasterzellen.
Die Elemente werden im Raster angeordnet, unabhängig davon, ob Sie die Zeilen und Spalten explizit definiert haben.
Standardmäßig versucht Grid, ein UI-Element in der verfügbaren Rasterzelle in der Zeile zu platzieren. Wenn das nicht möglich ist, wird es in einer verfügbaren Rasterzelle in der nächsten Zeile platziert.
Wenn keine leeren Zellen vorhanden sind, erstellt Grid eine neue Zeile.
Im folgenden Beispiel hat das Raster sechs Rasterzellen und in jeder wird eine Karte platziert (Abbildung 1).
Jede Rasterzelle ist 160dp × 90dp groß, sodass die Gesamtgröße des Rasters 320dp × 270dp beträgt.
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
Wenn Sie dieses Standardverhalten in „Spaltenweise füllen“ ändern möchten,
legen Sie die flow-Property auf GridFlow.Column fest.
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } gap(8.dp) flow = GridFlow.Column // Grid tries to place items to fill the column }, ) { Card1() Card2() Card3() Card4() Card5() Card6() }
GridFlow.Row (links) und GridFlow.Column (rechts).
Track-Größen verwalten
Zeilen und Spalten werden zusammen als ein Raster-Track bezeichnet. Sie können die Größe eines Raster-Tracks mit einer der folgenden Methoden angeben:
- Fest (
Dp): Weist eine bestimmte Größe zu (z.B.column(180.dp)). - Prozentual (
Float): Weist einen Prozentsatz des insgesamt verfügbaren Platzes von0.0fbis1.0fzu (z.B.row(0.5f)für 50%). - Flexibel (
Fr): Verteilt den verbleibenden Platz proportional, nachdem feste und prozentuale Tracks berechnet wurden. Wenn beispielsweise zwei Zeilen auf1.frund3.frfestgelegt sind, erhält die zweite Zeile 75% der verbleibenden Höhe. - Intrinsisch: Legt die Größe des Tracks basierend auf dem Inhalt fest. Weitere Informationen finden Sie unter Größe von Raster-Tracks intrinsisch bestimmen.
Im folgenden Beispiel werden die verschiedenen Optionen zur Größenbestimmung von Tracks verwendet, um die Zeilenhöhen zu definieren:
Grid( config = { column(1f) row(100.dp) row(0.2f) row(1.fr) row(GridTrackSize.Auto) }, modifier = Modifier.height(480.dp) ) { PastelRedCard("Fixed(100.dp)") PastelGreenCard("Percentage(0.2f)") PastelBlueCard("Flex(1.fr)") PastelYellowCard("Auto") }
Grid definiert wurden.
Mindestgröße für flexible Raster-Tracks festlegen
Wenn in einem Raster-Container kein Platz mehr vorhanden ist, kann ein standardmäßiger flexibler Track auf 0.dp verkleinert werden.
Um dies zu verhindern und dafür zu sorgen, dass Inhalte nicht zu klein dargestellt werden,
verwenden Sie GridTrackSize.MinMax
um eine explizite Mindestgröße zu erzwingen und den Track gleichzeitig flexibel zu halten.
Im folgenden Beispiel werden der ersten Zeile mindestens 100.dp zugewiesen:
Grid( config = { column(1f) // The first row has a minimum height of 100.dp and can expand to // the half of the remaining space. row(GridTrackSize.MinMax(100.dp, 1.fr)) // The second row takes the half of the remaining space. row(1.fr) // The third row has a fixed height of 200.dp. row(200.dp) }, modifier = Modifier.size(360.dp) // Total grid height is 360.dp ) { PastelRedCard("MinMax(100.dp, 1.fr)") PastelGreenCard("Flex(1.fr)") PastelBlueCard("Fixed(200.dp)") }
100.dp.
Mindestgröße für Raster-Tracks festlegen, um Lazy Lists zu platzieren
Standardmäßige flexible Tracks fragen automatisch die intrinsischen Größen ihrer untergeordneten Elemente ab, um eine Basisgröße festzulegen.
Jetpack Compose verbietet jedoch das Abfragen der intrinsischen Größen von
SubcomposeLayout, das Komponenten unterstützt,
wie LazyColumn und LazyRow.
Wenn Sie eine Lazy List in einem standardmäßigen flexiblen Track platzieren, führt das zu
einem IllegalStateException Absturz.
Um Lazy Lists sicher in einem flexiblen Raster-Track zu platzieren, verwenden Sie MinMax mit einer expliziten Mindestgröße (z. B. 0.dp), um den intrinsischen Messdurchlauf zu umgehen.
Grid( config = { column(1f) // The first row's height is determined by the height of the Text composable. row(GridTrackSize.Auto) // The second row occupies the remaining space, allowing the LazyColumn to scroll. row(GridTrackSize.MinMax(0.dp, 1.fr)) gap(8.dp) }, modifier = Modifier.size(width = 170.dp, height = 240.dp) ) { Text("LazyColumn in a Grid") // The LazyColumn is placed in the second row, filling the remaining space. LazyColumn(verticalArrangement = Arrangement.spacedBy(4.dp)) { items(100) { number -> PastelGreenCard("Card $number") } } }
LazyColumn in einer Rasterzelle.
Größe von Raster-Tracks intrinsisch bestimmen
Sie können die intrinsische Größenbestimmung für ein Grid
verwenden, wenn das Layout an den Inhalt angepasst werden soll,
anstatt es in einen festen Container zu zwingen.
Die Größe des Raster-Tracks wird mit den folgenden Werten bestimmt:
GridTrackSize.MaxContent: Verwenden Sie die maximale intrinsische Größe des Inhalts. Die Breite wird beispielsweise durch die vollständige Länge des Texts in einem Textblock ohne Umbruch bestimmt.GridTrackSize.MinContent: Verwenden Sie die minimale intrinsische Größe des Inhalts. Die Breite wird beispielsweise durch das längste einzelne Wort in einem Textblock bestimmt.GridTrackSize.Auto: Verwenden Sie eine flexible Größe für einen Track, die sich an den verfügbaren Platz anpasst. Standardmäßig verhält sie sich wieMaxContent, wird aber verkleinert und umbrochen, damit der Inhalt in den übergeordneten Container passt.
Im folgenden Beispiel werden zwei Texte nebeneinander platziert. Die Spaltengröße für den ersten Text wird durch die erforderliche Mindestbreite für die Anzeige des Texts bestimmt. Die Breite der zweiten Spalte hängt von der erforderlichen maximalen Breite des Texts ab.
Grid( config = { column(GridTrackSize.MinContent) column(GridTrackSize.MaxContent) row(1.0f) }, modifier = Modifier.width(480.dp) ) { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.") Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras imperdiet.") }
Abstände zwischen Zeilen und Spalten festlegen
Nachdem Sie die Größe Ihrer Raster-Tracks festgelegt haben,
können Sie den Rasterabstand ändern, um den Abstand zwischen den Tracks zu optimieren.
Sie können den Spaltenabstand mit der columnGap Funktion,
und den Zeilenabstand mit rowGap angeben. Im folgenden Beispiel beträgt der Abstand zwischen den Zeilen 16dp und der Abstand zwischen den Spalten 8dp (Abbildung 5).
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } rowGap(16.dp) columnGap(8.dp) } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
Sie können auch die praktische Funktion gap
verwenden, um Abstände mit derselben Spalten- und Zeilengröße zu definieren,
und Spalten- und Abstandsgrößen mit einer einzigen Funktion separat zu definieren.
Mit dem folgenden Code werden dem Raster Abstände von 8dp hinzugefügt:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } gap(8.dp) // Equivalent to columnGap(8.dp) and rowGap(8.dp) } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
Rasterbereiche mit benannten Bereichen definieren
Mit benannten Bereichen können Sie Gruppen von Rasterzellen, die als Rasterbereiche bezeichnet werden, Namen zuweisen. Sie können diese Namen anstelle von Koordinatenindizes verwenden, wenn Sie UI-Elemente im Raster platzieren.
Die Verwendung benannter Bereiche hat zwei Hauptvorteile für die Lesbarkeit des Codes:
- Beim Definieren des Rasterlayouts sind Zweck und Platzierung der erwarteten Inhalte klar.
- Beim Hinzufügen der Inhalte ist der Zweck dieser Inhalte klar.
Um komplexe Layouts übersichtlich zu gestalten, können Sie die physische Rasterstruktur von der Platzierung untergeordneter Elemente entkoppeln, indem Sie semantische Rasterbereiche definieren.
Verwenden Sie in der config-Lambda-Funktion die area-Funktion in
GridConfigurationScope, um benannte Bereiche im Raster zu registrieren.
Anschließend können Sie diesen Bereichen untergeordnete zusammensetzbare Funktionen
mit dem gridItem Modifikator
und der entsprechenden Bereichs-ID zuweisen. Die Funktion area ordnet eine semantische ID (z. B. einen enum-Klassenwert oder einen Stringschlüssel) einer Reihe von physischen Rasterkoordinaten zu. Rasterlinien und -indizes sind 1-basiert (d. h. die erste Zeile ist 1 und die erste Spalte ist 1).
Sie definieren beispielsweise ein Raster mit vier Bereichs-IDs:
/** * An enum representing the IDs for named areas within the grid. */ enum class GridAreaNames { Area1, Area2, Area3, Area4 }
Geben Sie den Namen für den Bereich mit dem Parameter areaId zusammen mit den Zellkoordinaten und Spans des Bereichs an.
Der Modifikator gridItem verwendet areaId als Schlüssel, um jedes untergeordnete Element dem entsprechenden Rasterbereich zuzuweisen, wie im folgenden Beispiel gezeigt:
Grid( config = { // Define a single column that takes all available width. repeat(2) { column(0.5f) } // Define four rows, each taking 25% of the total height. repeat(4) { row(0.25f) } // Define named grid areas by associating an areaId with specific row and column indices. // Row and column indices are 1-based. area(areaId = GridAreaNames.Area1, row = 1, column = 1, columnSpan = 2) area(areaId = GridAreaNames.Area2, row = 2, column = 1, rowSpan = 3) area(areaId = GridAreaNames.Area3, rows = 2..3, columns = 2..2) area(areaId = GridAreaNames.Area4, row = 4, column = 2) gap(4.dp) }, modifier = Modifier.size(360.dp) ) { PastelRedCard( "Area 1", // Use Modifier.gridItem(areaId) to place this composable into the // grid area defined with the matching ID in the config block. modifier = Modifier.gridItem(areaId = GridAreaNames.Area1) ) PastelGreenCard( "Area 2", modifier = Modifier.gridItem(areaId = GridAreaNames.Area2) ) PastelBlueCard( "Area 3", modifier = Modifier.gridItem(areaId = GridAreaNames.Area3) ) PastelYellowCard( "Area 4", modifier = Modifier.gridItem(areaId = GridAreaNames.Area4) ) }
Mit benannten Bereichen können Sie das physische Layoutraster in der config-Lambda-Funktion neu organisieren oder anpassen (z. B. Zeilen, Spalten oder Track-Größen ändern), ohne die Reihenfolge oder Parameter der untergeordneten zusammensetzbaren Funktionen ändern zu müssen.