Grid

Composable Function

Common
@Composable
@ExperimentalGridApi
inline fun Grid(
    noinline config: GridConfigurationScope.() -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable GridScope.() -> Unit,
)

A 2D layout composable that arranges children into a grid of rows and columns.

The Grid allows defining explicit tracks (columns and rows) with various sizing capabilities, including fixed sizes (dp), flexible fractions (fr), percentages, and content-based sizing (Auto).

Key Features:

  • Explicit vs. Implicit: You define the main structure via config (explicit tracks). If items are placed outside these defined bounds, or if auto-placement creates new rows/columns, the grid automatically extends using implicit sizing (defaults to Auto).
  • Flexible Sizing: Use Fr units (e.g., 1.fr, 2.fr) to distribute available space proportionally among tracks.
  • Auto-placement: Items without a specific GridScope.gridItem modifier flow automatically into the next available cell based on the configured GridFlow. .

Parameters

configA block that defines the columns, rows, and gaps of the grid. This block runs during the measure pass, enabling efficient updates based on state.
modifierThe modifier to be applied to the layout.
contentThe content of the grid. Direct children can use GridScope.gridItem to configure their position and span.

Code Examples

GridWithAutoPlacement

@Composable
@OptIn(ExperimentalGridApi::class)
fun GridWithAutoPlacement() {
    Grid(
        config = {
            columns(Fixed(80.dp), Fixed(80.dp)) // Explicitly 2 columns
            // Rows are implicit
            flow = GridFlow.Row // Default
            gap(4.dp)
        }
    ) {
        // These items will fill row by row
        repeat(6) { index ->
            Text("Item $index", Modifier.background(Color(index * 40, 255 - index * 40, 128)))
        }
    }
}

GridWithSpanningItems

@Composable
@OptIn(ExperimentalGridApi::class)
fun GridWithSpanningItems() {
    Grid(
        config = {
            columns(Fixed(60.dp), Fixed(60.dp), Fixed(60.dp))
            rows(Fixed(40.dp), Fixed(40.dp))
            gap(4.dp)
        },
        modifier = Modifier.background(Color.LightGray),
    ) {
        Text("1x1", Modifier.gridItem(row = 1, column = 1).background(Color.White))
        Text(
            "1x2 span col",
            Modifier.gridItem(row = 1, column = 2, columnSpan = 2).background(Color.Cyan),
        )
        Text(
            "2x1 span row",
            Modifier.gridItem(row = 1, column = 1, rowSpan = 2).background(Color.Yellow),
        )
        Text("2x2 span all", Modifier.gridItem(rows = 1..2, columns = 2..3).background(Color.Green))
    }
}

SimpleGrid

@Composable
@OptIn(ExperimentalGridApi::class)
fun SimpleGrid() {
    Grid(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        config = {
            // Define 2 Columns:
            // Col 1: Fixed navigation sidebar width
            column(100.dp)
            // Col 2: Takes remaining space
            column(1.fr)
            // Define 3 Rows:
            // Row 1: Header (sized to content)
            row(GridTrackSize.Auto)
            // Row 2: Main Content (takes remaining height)
            row(1.fr)
            // Row 3: Footer (fixed height)
            row(60.dp)
            // Add 8dp space between all cells
            gap(8.dp)
        },
    ) {
        // 1. Header: Spans across both columns at the top
        Box(
            modifier =
                Modifier.gridItem(row = 1, column = 1, columnSpan = 2)
                    .background(Color.Blue)
                    .fillMaxSize(),
            contentAlignment = Alignment.Center,
        ) {
            Text("Header", color = Color.White)
        }
        // 2. Sidebar: Left column, middle row
        Box(
            modifier = Modifier.gridItem(row = 2, column = 1).background(Color.Green).fillMaxSize(),
            contentAlignment = Alignment.Center,
        ) {
            Text("Nav", color = Color.Black)
        }
        // 3. Main Content: Right column, middle row
        Box(
            modifier =
                Modifier.gridItem(row = 2, column = 2).background(Color.LightGray).fillMaxSize(),
            contentAlignment = Alignment.Center,
        ) {
            Text("Main Content Area")
        }
        // 4. Footer: Spans both columns at the bottom
        Box(
            modifier =
                Modifier.gridItem(row = 3, columnSpan = 2) // Column defaults to 1 if unspecified
                    .background(Color.Magenta)
                    .fillMaxSize(),
            contentAlignment = Alignment.Center,
        ) {
            Text("Footer", color = Color.White)
        }
    }
}