Imposta le proprietà del contenitore

Puoi definire una configurazione del contenitore griglia per creare layout flessibili che si adattano a diverse dimensioni dello schermo e tipi di contenuti. Questa pagina descrive come:

Definisci una griglia

Una griglia è composta da colonne e righe. Il composable Grid ha un parametro config che accetta una funzione lambda per definire le colonne e le righe all'interno di GridConfigurationScope. L'esempio seguente definisce una griglia con tre righe e due colonne, ciascuna con una dimensione fissa specificata in Dp:

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
}

Posiziona gli elementi in una griglia

Grid prende gli elementi UI nella funzione lambda content e li inserisce nelle celle della griglia. La griglia dispone gli elementi indipendentemente dal fatto che tu abbia definito esplicitamente le righe e le colonne. Per impostazione predefinita, Grid tenta di posizionare un elemento UI nella cella della griglia disponibile nella riga; se non è possibile, lo posiziona in una cella della griglia disponibile nella riga successiva. Se non ci sono celle vuote, Grid crea una nuova riga.

Nell'esempio seguente, la griglia ha sei celle e inserisce una scheda in ciascuna (Figura 1). Ogni cella della griglia è 160dp x 90dp, per una dimensione totale della griglia di 320dp x 270dp.

Grid(
    config = {
        repeat(2) {
            column(160.dp)
        }
        repeat(3) {
            row(90.dp)
        }
    }
) {
    Card1()
    Card2()
    Card3()
    Card4()
    Card5()
    Card6()
}

Sei schede sono disposte in una griglia con tre righe e due colonne.
Figura 1. Sei schede sono disposte in una griglia con tre righe e due colonne.

Per modificare questo comportamento predefinito in modo da riempire per colonna, imposta la proprietà flow su GridFlow.Column.

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()
}

La funzione di flusso cambia la direzione in cui posizionare gli elementi.
Figura 2. GridFlow.Row (a sinistra) e GridFlow.Column (a destra).

Gestisci il dimensionamento delle tracce

Le righe e le colonne sono collettivamente denominate pista della griglia. Puoi specificare le dimensioni di una traccia della griglia utilizzando uno dei seguenti metodi:

  • Fisso (Dp): alloca una dimensione specifica (ad es. column(180.dp)).
  • Percentuale (Float): alloca una percentuale dello spazio totale disponibile da 0.0f a 1.0f (ad es. row(0.5f) per il 50%).
  • Flessibile (Fr): distribuisce lo spazio rimanente in modo proporzionale dopo il calcolo delle tracce fisse e percentuali. Ad esempio, se due righe sono impostate su 1.fr e 3.fr, quest'ultima riceve il 75% dell'altezza rimanente.
  • Intrinseco: dimensiona la traccia in base ai contenuti al suo interno. Per saperne di più, consulta Determinare intrinsecamente le dimensioni della traccia della griglia.

L'esempio seguente utilizza le diverse opzioni di dimensionamento delle tracce per definire le altezze delle righe:

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")

}

Altezze delle righe definite utilizzando le quattro opzioni principali di dimensionamento delle tracce.
Figura 3. Altezze delle righe definite utilizzando le quattro opzioni principali di dimensionamento della traccia in Grid.

Imposta la dimensione minima per le tracce della griglia flessibile

Quando un container griglia non ha più spazio, una traccia flessibile standard può ridursi a 0.dp. Per evitare questo problema e assicurarti che i contenuti non vengano schiacciati, utilizza GridTrackSize.MinMax per applicare una dimensione minima esplicita, mantenendo al contempo la flessibilità della traccia.

L'esempio seguente assegna almeno 100.dp alla prima riga:

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)")
}

Altezze delle righe definite utilizzando le quattro opzioni principali di dimensionamento delle tracce.
Figura 4. La prima riga ha un'altezza di almeno 100.dp.

Imposta la dimensione minima della traccia della griglia per posizionare gli elenchi lazy

Le tracce flessibili standard eseguono automaticamente query sulle dimensioni intrinseche dei relativi elementi secondari per stabilire una dimensione di base. Tuttavia, Jetpack Compose vieta l'esecuzione di query sulle dimensioni intrinseche di SubcomposeLayout, che supporta componenti come LazyColumn e LazyRow.

L'inserimento di un elenco lazy all'interno di un track flessibile standard causa un arresto anomalo di IllegalStateException. Per posizionare in sicurezza gli elenchi lazy all'interno di una traccia di griglia flessibile, utilizza MinMax con una dimensione minima esplicita (ad esempio 0.dp) per bypassare il passaggio di misurazione intrinseca.

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")
        }
    }
}

Altezze delle righe definite utilizzando le quattro opzioni principali di dimensionamento delle tracce.
Figura 5. LazyColumn in una cella della griglia.

Determina la dimensione della traccia della griglia in modo intrinseco

Puoi utilizzare il dimensionamento intrinseco per un Grid quando vuoi che il layout si adatti ai contenuti, anziché forzarlo in un container fisso. La dimensione della griglia è determinata dai seguenti valori:

  • GridTrackSize.MaxContent: utilizza le dimensioni intrinseche massime dei contenuti (ad esempio, la larghezza è determinata dalla lunghezza totale del testo in un blocco di testo senza ritorno a capo).
  • GridTrackSize.MinContent: utilizza le dimensioni intrinseche minime dei contenuti (ad esempio, la larghezza è determinata dalla singola parola più lunga in un blocco di testo).
  • GridTrackSize.Auto: utilizza una dimensione flessibile per una traccia che si adatta in base allo spazio disponibile. Per impostazione predefinita, si comporta come MaxContent, ma riduce e adatta i contenuti in modo che rientrino nel contenitore principale.

L'esempio seguente posiziona due testi affiancati. La dimensione della colonna per il primo testo è determinata dalla larghezza minima richiesta per visualizzare il testo, mentre la larghezza della seconda colonna dipende dalla larghezza massima richiesta del testo.

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.")
}

Dimensioni intrinseche specificate nelle colonne.
Figura 5. Dimensioni intrinseche specificate nelle colonne.

Imposta gli spazi tra righe e colonne

Una volta dimensionate le tracce della griglia, puoi modificare la distanza tra gli elementi della griglia per perfezionare la spaziatura tra le tracce. Puoi specificare lo spazio tra le colonne con la funzione columnGap e lo spazio tra le righe con rowGap. Nell'esempio seguente, c'è uno spazio di 16dp tra ogni riga e uno spazio di 8dp tra ogni colonna (Figura 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()
}

Spazi tra righe e colonne.
Figura 6. Spazi tra righe e colonne.

Puoi anche utilizzare la comoda funzione gap per definire spazi vuoti della stessa dimensione di colonne e righe e per definire le dimensioni di colonne e spazi vuoti separatamente utilizzando un'unica funzione. Il seguente codice aggiunge spazi vuoti di 8dp alla griglia:

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()
}

Definisci le aree della griglia con aree denominate

Le aree con nome ti consentono di assegnare nomi a gruppi di celle della griglia, chiamati aree della griglia. Puoi utilizzare questi nomi anziché gli indici delle coordinate quando posizioni gli elementi UI nella griglia.

L'utilizzo di aree con nome offre due vantaggi principali per la leggibilità del codice:

  • Quando definisci il layout della griglia, lo scopo e la posizione dei contenuti previsti sono chiari.
  • Quando aggiungi i contenuti, lo scopo di questi contenuti è chiaro.

Per organizzare chiaramente i layout complessi, puoi separare la struttura fisica della griglia dal posizionamento degli elementi secondari definendo aree della griglia semantiche.

All'interno della funzione lambda config, utilizza la funzione area in GridConfigurationScope per registrare le aree con nome nella griglia. Puoi quindi assegnare elementi componibili secondari a queste aree utilizzando il modificatore gridItem con l'identificatore dell'area corrispondente. La funzione area mappa un identificatore semantico (ad esempio un valore della classe enum o una chiave di stringa) a un insieme di coordinate della griglia fisica. Le linee e gli indici della griglia sono basati su 1 (ovvero, la prima riga è 1 e la prima colonna è 1).

Ad esempio, definisci una griglia con quattro ID area:

/**
 * An enum representing the IDs for named areas within the grid.
 */
enum class GridAreaNames {
    Area1,
    Area2,
    Area3,
    Area4
}

Specifica il nome dell'area utilizzando il parametro areaId insieme alle coordinate e agli intervalli delle celle dell'area. Il modificatore gridItem utilizza areaId come chiave per assegnare ogni elemento secondario alla relativa area della griglia designata, come mostrato nell'esempio seguente:

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)
    )
}

Utilizzando le aree denominate, puoi riorganizzare o regolare la griglia di layout fisico (ad esempio, modificando righe, colonne o dimensioni delle tracce) nella funzione lambda config senza dover modificare l'ordine o i parametri dei componibili secondari.