As of Jetpack Compose, a Recycler type of view is called Lazy.
For now, there are only Lazy Row and Lazy Column.
I have a Staggered Grid custom Composable, that is scrollable. But is there a way I can make it Lazy? Or is such an API not stable yet?
You can do the same effect in many ways, one of them is:
@Composable
fun StaggeredVerticalGrid(
modifier: Modifier = Modifier,
maxColumnWidth: Dp,
children: @Composable () -> Unit
) {
Layout(
children = children,
modifier = modifier
) { measurables, constraints ->
check(constraints.hasBoundedWidth) {
"Unbounded width not supported"
}
val columns = ceil(constraints.maxWidth / maxColumnWidth.toPx()).toInt()
val columnWidth = constraints.maxWidth / columns
val itemConstraints = constraints.copy(maxWidth = columnWidth)
val colHeights = IntArray(columns) { 0 } // track each column's height
val placeables = measurables.map { measurable ->
val column = shortestColumn(colHeights)
val placeable = measurable.measure(itemConstraints)
colHeights[column] += placeable.height
placeable
}
val height = colHeights.maxOrNull()?.coerceIn(constraints.minHeight, constraints.maxHeight)
?: constraints.minHeight
layout(
width = constraints.maxWidth,
height = height
) {
val colY = IntArray(columns) { 0 }
placeables.forEach { placeable ->
val column = shortestColumn(colY)
placeable.place(
x = columnWidth * column,
y = colY[column]
)
colY[column] += placeable.height
}
}
}
}
private fun shortestColumn(colHeights: IntArray): Int {
var minHeight = Int.MAX_VALUE
var column = 0
colHeights.forEachIndexed { index, height ->
if (height < minHeight) {
minHeight = height
column = index
}
}
return column
}
extracted from Owl sample app, Don't forget to wrap/call this Composable inside ScrollableColumn.
EDIT: with the release of compose 1.0.0-alpha09, now you have official LazyVerticalGrid, check release notes
LazyVerticalGrid to achieve staggered effect if you want something perfectIf you are implementing a custom staggered grid, I would say you implement a staggered row instead. Then create another Composable that receives the data and feeds it in the staggered rows while internally using a lazy column for each row. I am not asking you to implement something new. Just tweak the existing implementation a bit and it will be a great performance boost.
Also, if your data is not big enough, it is okay to not use lazy containers.