Scope for the children of Grid.

Summary

Constants

const Int

Sentinel value indicating that a grid position (row or column) is not manually specified and should be determined automatically by the layout flow.

Cmn
const Int

The maximum allowed index for a row or column (inclusive).

Cmn

Public functions

Modifier

Configures the position and alignment of an element within a Grid layout by referencing a named area.

Cmn
Modifier
Modifier.gridItem(rows: IntRange, columns: IntRange, alignment: Alignment)

Configures the position, span, and alignment of an element within a Grid layout using ranges.

Cmn
Modifier
Modifier.gridItem(
    row: @IntRange(from = -1000, to = 1000) Int,
    column: @IntRange(from = -1000, to = 1000) Int,
    rowSpan: @IntRange(from = 1) Int,
    columnSpan: @IntRange(from = 1) Int,
    alignment: Alignment
)

Configures the position, span, and alignment of an element within a Grid layout.

Cmn

Constants

GridIndexUnspecified

@ExperimentalGridApi
const val GridIndexUnspecified = 0: Int

Sentinel value indicating that a grid position (row or column) is not manually specified and should be determined automatically by the layout flow.

MaxGridIndex

@ExperimentalGridApi
const val MaxGridIndex = 1000: Int

The maximum allowed index for a row or column (inclusive).

This hard limit prevents performance degradation, layout timeouts, or memory issues potentially caused by accidental loop overflows or unreasonably large sparse grid definitions.

Note: This value MUST NOT exceed Short.MAX_VALUE (32767). Named Area bounds are bit-packed into 16-bit segments, and larger values will silently truncate.

Public functions

@ExperimentalGridApi
fun Modifier.gridItem(areaId: Any, alignment: Alignment = Alignment.TopStart): Modifier

Configures the position and alignment of an element within a Grid layout by referencing a named area.

Apply this modifier to direct children of a Grid composable. The areaId must correspond to an identifier defined using GridConfigurationScope.area within the config block of the Grid.

Multiple Items & Overlapping:

  • 2D Areas: If multiple items are assigned to the same fully specified 2D area (both row and column are fixed), they will stack on top of each other within those bounds. Z-ordering is determined by composition order (items declared later draw on top, mirroring Box).

  • 1D Areas & Flow: If the referenced area is one-dimensional (e.g., it defines a row but leaves the column unspecified), placing multiple items into it triggers auto-flow. The items will automatically flow into the next available cells within that specific track.

Fallback Behavior for Unknown Areas: If the provided areaId identifier is not registered in the Grid configuration, this item will silently fall back to automatic placement to prevent runtime crashes.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Grid
import androidx.compose.foundation.layout.columns
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.rows
import androidx.compose.material.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Grid(
    modifier = Modifier.fillMaxSize().padding(16.dp),
    config = {
        // 1. Define Physical Tracks
        column(100.dp) // Sidebar track
        column(1.fr) // Main content track

        row(60.dp) // Header track
        row(1.fr) // Main content track
        row(50.dp) // Footer track

        gap(8.dp)

        // 2. Map Semantic Strings to physical coordinates
        area("header", row = 1, column = 1, columnSpan = 2)
        area("sidebar", row = 2, column = 1)
        area("content", row = 2, column = 2)
        area("footer", rows = 3..3, columns = 1..2)
    },
) {
    // 3. Place items purely by semantic intent!
    Box(
        modifier = Modifier.gridItem("header").background(Color.DarkGray).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Header", color = Color.White)
    }

    Box(
        modifier = Modifier.gridItem("sidebar").background(Color.LightGray).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Sidebar")
    }

    Box(
        modifier = Modifier.gridItem("content").background(Color.Cyan).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Main Content")
    }

    Box(
        modifier = Modifier.gridItem("footer").background(Color.Gray).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Footer", color = Color.White)
    }
}
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Grid
import androidx.compose.foundation.layout.columns
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Grid(
    modifier = Modifier.fillMaxSize().padding(16.dp),
    config = {
        // 1. Define physical tracks
        column(100.dp) // Sidebar track
        column(1.fr) // Main content track

        row(60.dp) // Header track
        row(1.fr) // Main content track

        gap(8.dp)

        // 2. Define 1-Dimensional Areas
        // 1D Area: Fix the row, leave column unspecified
        area("header", row = 1)

        // 1D Area: Fix the column, leave row unspecified
        area("sidebar", column = 1)

        // Fully specified 2D area
        area("content", row = 2, column = 2)
    },
) {
    // Because "header" is 1D, items automatically flow into available columns!
    // Logo takes the first available slot (row 1, col 1)
    Box(
        modifier = Modifier.gridItem("header").background(Color.Red).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Logo", color = Color.White)
    }

    // Search automatically flows into the next available slot (row 1, col 2)
    Box(
        modifier = Modifier.gridItem("header").background(Color.Magenta).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Search Bar", color = Color.White)
    }

    // Because "sidebar" is 1D (col=1), it flows into the next available row.
    // Since (row 1, col 1) is taken by Logo, this flows to (row 2, col 1).
    Box(
        modifier = Modifier.gridItem("sidebar").background(Color.Blue).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Sidebar Menu", color = Color.White)
    }

    // Exact 2D placement
    Box(
        modifier = Modifier.gridItem("content").background(Color.Green).fillMaxSize(),
        contentAlignment = Alignment.Center,
    ) {
        Text("Main Content", color = Color.White)
    }
}
Parameters
areaId: Any

The user-defined identifier corresponding to the area defined in the Grid configuration. This identifier must have a stable equals() and hashCode() implementation (e.g., an enum, String, data class, or singleton object) to correctly match the area registered in the configuration.

alignment: Alignment = Alignment.TopStart

Specifies how the content should be aligned within the grid cell(s). Defaults to Alignment.TopStart.

Modifier.gridItem

fun Modifier.gridItem(
    rows: IntRange,
    columns: IntRange,
    alignment: Alignment = Alignment.TopStart
): Modifier

Configures the position, span, and alignment of an element within a Grid layout using ranges.

This convenience overload converts IntRange inputs into row/column indices and spans.

Equivalence:

  • rows = 4..5 maps to row = 4, rowSpan = 2.

  • columns = 1..1 maps to column = 1, columnSpan = 1.

Example: Modifier.gridItem(rows = 2..3, columns = 1..2) is functionally equivalent to Modifier.gridItem(row = 2, rowSpan = 2, column = 1, columnSpan = 2).

Parameters
rows: IntRange

The range of rows to occupy (e.g., 1..2). The start determines the row index, and the size of the range determines the span.

columns: IntRange

The range of columns to occupy (e.g., 1..3). The start determines the column index, and the size of the range determines the span.

alignment: Alignment = Alignment.TopStart

Specifies how the content should be aligned within the grid cell(s). Defaults to Alignment.TopStart.

See also
gridItem

Modifier.gridItem

fun Modifier.gridItem(
    row: @IntRange(from = -1000, to = 1000) Int = GridIndexUnspecified,
    column: @IntRange(from = -1000, to = 1000) Int = GridIndexUnspecified,
    rowSpan: @IntRange(from = 1) Int = 1,
    columnSpan: @IntRange(from = 1) Int = 1,
    alignment: Alignment = Alignment.TopStart
): Modifier

Configures the position, span, and alignment of an element within a Grid layout.

Apply this modifier to direct children of a Grid composable.

Default Behavior: If this modifier is not applied to a child, the child will be automatically placed in the next available cell (spanning 1 row and 1 column) according to the configured GridFlow.

Indexing: Grid row and column indices are 1-based.

  • Positive values count from the start (1 is the first row/column).

  • Negative values count from the end (-1 is the last explicitly defined row/column).

Auto-placement: If row or column are left to their default value (GridIndexUnspecified), the Grid layout will automatically place the item based on the configured GridFlow.

Parameters
row: @IntRange(from = -1000, to = 1000) Int = GridIndexUnspecified

The specific 1-based row index to place the item in. Positive values count from the start (1 is the first row). Negative values count from the end (-1 is the last row). Must be within the range [-MaxGridIndex, MaxGridIndex]. Defaults to GridIndexUnspecified for auto-placement.

column: @IntRange(from = -1000, to = 1000) Int = GridIndexUnspecified

The specific 1-based column index to place the item in. Positive values count from the start (1 is the first column). Negative values count from the end (-1 is the last column). Must be within the range [-MaxGridIndex, MaxGridIndex]. Defaults to GridIndexUnspecified for auto-placement.

rowSpan: @IntRange(from = 1) Int = 1

The number of rows this item should occupy. Must be greater than 0. Defaults to 1.

columnSpan: @IntRange(from = 1) Int = 1

The number of columns this item should occupy. Must be greater than 0. Defaults to 1.

alignment: Alignment = Alignment.TopStart

Specifies how the content should be aligned within the grid cell(s) it occupies. Defaults to Alignment.TopStart.

Throws
IllegalArgumentException

if row or column (when specified) are outside the valid range, or if rowSpan or columnSpan are less than 1.