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: Richten Sie die grundlegende Struktur aus Zeilen und Spalten ein.
- Elemente in einem Raster platzieren: Hier erfahren Sie, wie Elemente in Rasterzellen platziert werden und wie Sie die Flussrichtung ändern.
- Spurgrößen verwalten: Mit festen, prozentualen, flexiblen und intrinsischen Größen können Sie die Spurgrößen festlegen.
- Abstände festlegen: Hier können Sie die Abstände zwischen Zeilen und Spalten verwalten.
Raster definieren
Ein Raster besteht aus Spalten und Zeilen.
Die zusammensetzbare Funktion Grid hat einen config-Parameter, der ein Lambda akzeptiert, um die Spalten und Zeilen in GridConfigurationScope zu definieren.
Im folgenden Beispiel wird ein Raster mit drei Zeilen und zwei Spalten definiert, die jeweils eine feste Größe haben, die in Dp angegeben ist:
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { }
Elemente in einem Raster anordnen
Grid nimmt die UI-Elemente im content-Lambda und platziert sie in Rasterzellen.
Im Raster werden Elemente unabhängig davon angeordnet, 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, wird mit Grid eine neue Zeile erstellt.
Im folgenden Beispiel hat das Raster sechs Rasterzellen und in jeder wird eine Karte platziert (Abbildung 1).
Jede Zelle im Raster ist 160dp × 90dp groß. Die Gesamtgröße des Rasters beträgt 320dp × 270dp.
Grid( config = { repeat(2) { column(160.dp) } repeat(3) { row(90.dp) } } ) { Card1() Card2() Card3() Card4() Card5() Card6() }
Wenn Sie dieses Standardverhalten in „Spaltenweise ausfüllen“ ändern möchten, legen Sie die Eigenschaft flow 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).
Trackgröße verwalten
Zeilen und Spalten werden zusammen als Rasterspur bezeichnet. Sie können die Größe eines Grid-Tracks mit einer der folgenden Methoden angeben:
- Fest (
Dp): Weist eine bestimmte Größe zu, z.B.column(180.dp). - Prozentsatz (
Float): Weist einen Prozentsatz des insgesamt verfügbaren Speicherplatzes von0.0fbis1.0fzu (z.B.row(0.5f)für 50%). - Flexibel (
Fr): Der verbleibende Speicherplatz wird proportional verteilt, nachdem die Tracks mit festen und prozentualen Werten berechnet wurden. Wenn beispielsweise zwei Zeilen auf1.frund3.frfestgelegt sind, erhält die zweite Zeile 75% der verbleibenden Höhe. - Intrinsic: Die Größe des Tracks wird basierend auf dem Inhalt darin festgelegt. Weitere Informationen finden Sie unter Größe von Grid-Tracks intrinsisch bestimmen.
Im folgenden Beispiel werden die verschiedenen Optionen für die Größenanpassung 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 werden.
Mindestgröße für flexible Rasterspalten festlegen
Wenn in einem Grid-Container kein Platz mehr vorhanden ist, kann ein standardmäßiger flexibler Track auf 0.dp verkleinert werden.
Um dies zu verhindern und sicherzustellen, dass Inhalte nicht komprimiert werden, verwenden Sie GridTrackSize.MinMax, um eine explizite Mindestgröße festzulegen und gleichzeitig den Track 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 zum Platzieren von Lazy Lists festlegen
Bei Standard-Flex-Tracks werden automatisch die intrinsischen Größen der untergeordneten Elemente abgefragt, um eine Basisgröße festzulegen.
In Jetpack Compose ist es jedoch nicht möglich, die intrinsischen Größen von SubcomposeLayout abzufragen, die Komponenten wie LazyColumn und LazyRow zugrunde liegen.
Wenn Sie eine Lazy List in einen Standard-Flexiblen Track einfügen, kommt es zu einem IllegalStateException-Absturz.
Wenn Sie Lazy Lists sicher in einem flexiblen Grid-Track platzieren möchten, 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 Rastertracks intrinsisch bestimmen
Sie können Intrinsic Sizing 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 der Grid-Tracks wird mit den folgenden Werten bestimmt:
GridTrackSize.MaxContent: Die maximale intrinsische Größe des Inhalts verwenden (z.B. wird die Breite durch die volle Länge des Texts in einem Textblock ohne Umbruch bestimmt).GridTrackSize.MinContent: Verwenden Sie die minimale intrinsische Größe des Inhalts (z.B. wird die Breite 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. Das Verhalten entspricht standardmäßigMaxContent, aber der Inhalt wird verkleinert und umgebrochen, damit er in den übergeordneten Container passt.
Im folgenden Beispiel werden zwei Textblöcke 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 die Rasterspuren dimensioniert wurden, können Sie den Rasterabstand anpassen, um den Abstand zwischen den Spuren zu optimieren.
Sie können den Spaltenabstand mit der Funktion columnGap und den Zeilenabstand mit rowGap angeben. Im folgenden Beispiel ist zwischen den einzelnen Zeilen eine Lücke von 16dp und zwischen den einzelnen Spalten eine Lücke von 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 Lücken mit derselben Spalten- und Zeilengröße zu definieren und Spalten- und Lückengrößen mit einer einzigen Funktion separat zu definieren.
Mit dem folgenden Code werden dem Raster 8dp-Lücken 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 Tabellenzellen, die als Tabellenbereiche bezeichnet werden, Namen zuweisen. Sie können diese Namen anstelle von Koordinatenindexen verwenden, wenn Sie UI-Elemente im Raster platzieren.
Die Verwendung benannter Bereiche hat zwei wesentliche Vorteile für die Lesbarkeit des Codes:
- Bei der Definition 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 Lambda-Funktion config die Funktion area in GridConfigurationScope, um benannte Bereiche im Raster zu registrieren.
Anschließend können Sie diesen Bereichen untergeordnete Composables mit dem Modifier gridItem und der entsprechenden Bereichs-ID zuweisen. Die Funktion area ordnet einen semantischen Bezeichner (z. B. einen enum-Klassenwert oder einen Stringschlüssel) einer Reihe von physischen Rasterkoordinaten zu. Gitternetzlinien und Indexe sind 1-basiert. Das bedeutet, dass die erste Zeile 1 und die erste Spalte 1 ist.
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 Spannen des Bereichs an.
Mit dem Modifikator gridItem wird areaId als Schlüssel verwendet, um jedes untergeordnete Element seinem zugewiesenen 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 Trackgrößen ändern, ohne die Reihenfolge oder Parameter der untergeordneten Composables ändern zu müssen.