Définir les propriétés du conteneur

Vous pouvez définir une configuration de conteneur de grille pour créer des mises en page flexibles qui s'adaptent à différentes tailles d'écran et types de contenu. Cette page explique comment effectuer les opérations suivantes :

Définir une grille

Une grille se compose de colonnes et de lignes. Le composable Grid comporte un paramètre config qui accepte un lambda pour définir les colonnes et les lignes dans GridConfigurationScope. L'exemple suivant définit une grille comportant trois lignes et deux colonnes, chacune avec une taille fixe spécifiée dans Dp :

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

Placer des éléments dans une grille

Grid prend les éléments d'UI dans le lambda content et les place dans des cellules de grille. La grille organise les éléments, que vous ayez défini explicitement les lignes et les colonnes ou non. Par défaut, Grid tente de placer un élément d'interface utilisateur dans la cellule de grille disponible de la ligne. Si ce n'est pas possible, il le place dans une cellule de grille disponible de la ligne suivante. Si aucune cellule n'est vide, Grid crée une ligne.

Dans l'exemple suivant, la grille comporte six cellules et place une carte dans chacune d'elles (figure 1). Chaque cellule de la grille mesure 160dp x 90dp, ce qui porte la taille totale de la grille à 320dp x 270dp.

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

Six cartes sont placées dans une grille de trois lignes et deux colonnes.
Figure 1. Six cartes sont placées dans une grille de trois lignes et deux colonnes.

Pour modifier ce comportement par défaut et remplir les données par colonne, définissez la propriété flow sur 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 fonction de flux modifie la direction dans laquelle les éléments sont placés.
Figure 2. GridFlow.Row (à gauche) et GridFlow.Column (à droite).

Gérer la taille des pistes

Les lignes et les colonnes sont collectivement appelées piste de grille. Vous pouvez spécifier la taille d'une piste de grille à l'aide de l'une des méthodes suivantes :

  • Fixe (Dp) : alloue une taille spécifique (par exemple, column(180.dp)).
  • Pourcentage (Float) : alloue un pourcentage de l'espace total disponible de 0.0f à 1.0f (par exemple, row(0.5f) pour 50%).
  • Flexible (Fr) : répartit l'espace restant de manière proportionnelle une fois les pistes fixes et en pourcentage calculées. Par exemple, si deux lignes sont définies sur 1.fr et 3.fr, la seconde reçoit 75% de la hauteur restante.
  • Intrinsèque : dimensionne la piste en fonction du contenu qu'elle contient. Pour en savoir plus, consultez Déterminer intrinsèquement la taille des pistes de la grille.

L'exemple suivant utilise les différentes options de dimensionnement des pistes pour définir la hauteur des lignes :

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

}

Hauteurs de ligne définies à l'aide des quatre options principales de dimensionnement des pistes.
Figure 3. Hauteurs de ligne définies à l'aide des quatre principales options de dimensionnement des pistes dans Grid.

Définir la taille minimale des pistes de grille flexibles

Lorsqu'un conteneur de grille n'a plus d'espace, une piste flexible standard peut être réduite à 0.dp. Pour éviter cela et vous assurer que le contenu n'est pas écrasé, utilisez GridTrackSize.MinMax pour appliquer une taille minimale explicite tout en conservant la flexibilité de la piste.

L'exemple suivant alloue au moins 100.dp à la première ligne :

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

Hauteurs de ligne définies à l'aide des quatre options principales de dimensionnement des pistes.
Figure 4 : La première ligne a une hauteur d'au moins 100.dp.

Définir la taille minimale de la piste de grille pour placer les listes différées

Les pistes flexibles standards interrogent automatiquement les tailles intrinsèques de leurs enfants pour établir une taille de base. Toutefois, Jetpack Compose interdit d'interroger les tailles intrinsèques de SubcomposeLayout, qui prend en charge les composants, tels que LazyColumn et LazyRow.

Placer une liste inactive dans une piste flexible standard provoque un plantage IllegalStateException. Pour placer des listes différées de manière sécurisée dans une piste de grille flexible, utilisez MinMax avec une taille minimale explicite (telle que 0.dp) pour contourner la passe de mesure intrinsèque.

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

Hauteurs de ligne définies à l'aide des quatre options principales de dimensionnement des pistes.
Figure 5. LazyColumn dans une cellule de la grille.

Déterminer intrinsèquement la taille des pistes de grille

Vous pouvez utiliser le dimensionnement intrinsèque pour un Grid lorsque vous souhaitez que la mise en page s'adapte au contenu, plutôt que de le forcer dans un conteneur fixe. La taille de la piste de grille est déterminée par les valeurs suivantes :

  • GridTrackSize.MaxContent : utilisez la taille intrinsèque maximale du contenu (par exemple, la largeur est déterminée par la longueur totale du texte dans un bloc de texte sans retour à la ligne).
  • GridTrackSize.MinContent : utilisez la taille intrinsèque minimale du contenu (par exemple, la largeur est déterminée par le mot le plus long d'un bloc de texte).
  • GridTrackSize.Auto : utilisez une taille flexible pour une piste qui s'adapte en fonction de l'espace disponible. Il se comporte comme MaxContent par défaut, mais réduit et encapsule son contenu pour l'adapter au conteneur parent.

L'exemple suivant place deux textes côte à côte. La taille de la première colonne de texte est déterminée par la largeur minimale requise pour afficher le texte, tandis que la largeur de la deuxième colonne dépend de la largeur maximale requise pour le texte.

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

Tailles intrinsèques spécifiées dans les colonnes.
Figure 5. Tailles intrinsèques spécifiées dans les colonnes.

Définir des espaces entre les lignes et les colonnes

Une fois la taille de vos pistes de grille définie, vous pouvez modifier l'espacement de la grille pour affiner l'espacement entre les pistes. Vous pouvez spécifier l'espace entre les colonnes avec la fonction columnGap et l'espace entre les lignes avec rowGap. Dans l'exemple suivant, il existe un espace de 16dp entre chaque ligne et un espace de 8dp entre chaque colonne (figure 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()
}

Espaces entre les lignes et les colonnes.
Figure 6 : Espaces entre les lignes et les colonnes.

Vous pouvez également utiliser la fonction pratique gap pour définir des espaces de même taille pour les colonnes et les lignes, et pour définir séparément la taille des colonnes et des espaces à l'aide d'une seule fonction. Le code suivant ajoute des espaces 8dp à la grille :

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

Définir des zones de grille avec des zones nommées

Les zones nommées vous permettent d'associer des noms à des groupes de cellules de grille, appelées zones de grille. Vous pouvez utiliser ces noms au lieu des index de coordonnées lorsque vous placez des éléments d'interface utilisateur dans la grille.

L'utilisation de zones nommées présente deux principaux avantages pour la lisibilité du code :

  • Lorsque vous définissez la mise en page de la grille, l'objectif et l'emplacement du contenu attendu sont clairs.
  • L'objectif du contenu est clair lorsque vous l'ajoutez.

Pour organiser clairement des mises en page complexes, vous pouvez dissocier la structure de grille physique du placement des enfants en définissant des zones de grille sémantiques.

Dans l'expression lambda config, utilisez la fonction area dans GridConfigurationScope pour enregistrer les zones nommées dans la grille. Vous pouvez ensuite attribuer des composables enfants à ces zones à l'aide du modificateur gridItem avec l'identifiant de zone correspondant. La fonction area mappe un identifiant sémantique (tel qu'une valeur de classe enum ou une clé de chaîne) à un ensemble de coordonnées de grille physique. Les lignes et les index de la grille sont basés sur 1 (c'est-à-dire que la première ligne est 1 et la première colonne est 1).

Par exemple, vous définissez une grille comportant quatre ID de zone :

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

Indiquez le nom de la zone à l'aide du paramètre areaId, ainsi que les coordonnées et les étendues des cellules de la zone. Le modificateur gridItem utilise areaId comme clé pour attribuer chaque élément enfant à la zone de grille désignée, comme illustré dans l'exemple suivant :

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

En utilisant des zones nommées, vous pouvez réorganiser ou ajuster la grille de mise en page physique (par exemple, en modifiant les lignes, les colonnes ou les tailles de piste) dans le lambda config sans avoir à modifier l'ordre ni les paramètres des composables enfants.