LazyGridView¶
LazyGridView is CortenaUI's lazy 2D grid container. It composes only the cells currently visible in the viewport, making it the right tool for large grids — image galleries, product catalogs, icon pickers with hundreds of entries.
Concept¶
LazyGridView wraps LazyVerticalGrid (vertical) or LazyHorizontalGrid (horizontal) and adds CortenaUI's bounce overscroll, auto-hiding scroll indicator with drag-to-scrub, threshold auto-release, and motion-system-driven feel. Cells are described through Compose's standard LazyGridScope DSL so you keep item, items, and Modifier.animateItem().
Cell layout follows the same GridColumns contract as eager GridView:
GridColumns.Fixed(count)— fixed cell count per cross-axis line.GridColumns.Adaptive(minSize)— fits as many cells as possible while keeping each at leastminSizewide.
For vertical orientation, columns controls how many cells fit horizontally per row; for horizontal orientation, it controls how many cells fit vertically per column.
Key behaviors:
- Lazy composition: only cells in the viewport are composed. Scrolling thousands of items stays smooth.
- Bounce overscroll: rubber-band drag and threshold auto-release.
- Sticky header: emit
item(span = { GridItemSpan(maxLineSpan) }) { ... }to span a full line as a header. - Auto-hide indicator: fades on activity, hides after idle.
- Drag-to-scrub indicator: tap and drag the indicator to skim large grids.
API Reference¶
@Composable
fun LazyGridView(
columns: GridColumns,
modifier: Modifier = Modifier,
orientation: Orientation = Orientation.Vertical,
state: LazyGridState = rememberLazyGridState(),
enabled: Boolean = true,
reverseLayout: Boolean = false,
flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
contentPadding: PaddingValues = PaddingValues(0.dp),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
showScrollIndicator: Boolean = true,
indicatorThickness: Dp = 3.dp,
indicatorColor: Color = Color.Unspecified,
indicatorShape: Shape = CapsuleShape(),
indicatorPadding: Dp = 2.dp,
indicatorPosition: ScrollIndicatorPosition = ScrollIndicatorPosition.End,
autoHideIndicator: Boolean = true,
draggableIndicator: Boolean = true,
content: LazyGridScope.() -> Unit,
)
Parameters¶
| Name | Type | Description |
|---|---|---|
columns |
GridColumns |
Cross-axis sizing. See GridColumns. |
modifier |
Modifier |
Standard Compose modifier. |
orientation |
Orientation |
Vertical (LazyVerticalGrid) or Horizontal (LazyHorizontalGrid). Default: Vertical. |
state |
LazyGridState |
Hoistable grid state. Default: rememberLazyGridState(). |
enabled |
Boolean |
Enables user scroll input. Default: true. |
reverseLayout |
Boolean |
Reverses cell order along the main axis. Default: false. |
flingBehavior |
FlingBehavior |
Fling physics. Default: platform default. |
contentPadding |
PaddingValues |
Padding around the grid. Default: 0.dp. |
verticalArrangement |
Arrangement.Vertical |
Spacing between cells vertically. Default: Arrangement.Top. |
horizontalArrangement |
Arrangement.Horizontal |
Spacing between cells horizontally. Default: Arrangement.Start. |
showScrollIndicator |
Boolean |
Toggles the scroll indicator. Default: true. |
indicatorThickness |
Dp |
Indicator bar thickness. Default: 3.dp. |
indicatorColor |
Color |
Indicator color. Defaults to outline color from theme. |
indicatorShape |
Shape |
Indicator shape. Default: CapsuleShape(). |
indicatorPadding |
Dp |
Padding around the indicator. Default: 2.dp. |
indicatorPosition |
ScrollIndicatorPosition |
Start or End. Default: End. |
autoHideIndicator |
Boolean |
Fade indicator out after idle. Default: true. |
draggableIndicator |
Boolean |
Allow user to drag the indicator to scrub. Default: true. |
content |
LazyGridScope.() -> Unit |
Standard LazyGridScope DSL — item, items, itemsIndexed. |
Examples¶
Adaptive image grid¶
LazyGridView(
columns = GridColumns.Adaptive(minSize = 120.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(8.dp),
) {
items(photos, key = { it.id }) { photo ->
AsyncImage(model = photo.url, modifier = Modifier.fillMaxWidth().aspectRatio(1f))
}
}
Fixed 4-column icon picker¶
LazyGridView(
columns = GridColumns.Fixed(4),
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
items(allIcons) { icon ->
Icon(imageVector = icon, contentDescription = null)
}
}
Section header that spans the full line¶
LazyGridView(columns = GridColumns.Fixed(3)) {
item(span = { GridItemSpan(maxLineSpan) }) {
Text("Section A", role = TextRole.TitleMedium)
}
items(sectionAItems) { ItemTile(it) }
item(span = { GridItemSpan(maxLineSpan) }) {
Text("Section B", role = TextRole.TitleMedium)
}
items(sectionBItems) { ItemTile(it) }
}
Programmatic scroll via hoisted state¶
val gridState = rememberLazyGridState()
val scope = rememberCoroutineScope()
LazyGridView(
columns = GridColumns.Adaptive(minSize = 100.dp),
state = gridState,
) {
items(catalog, key = { it.id }) { ProductCard(it) }
}
Button(onClick = { scope.launch { gridState.scrollToItem(0) } }) {
Text("Back to top")
}