Bradleycorn
11/04/2021, 2:03 PM@Composable
fun Grid(columns: Int, modifier: Modifier = Modifier, content: @Composable ()->Unit) {
Layout(content = content, modifier = modifier) { measurables, constraints ->
val rows = (measurables.size / columns) + (measurables.size.rem(columns).coerceAtMost(1))
val maxColWidth = constraints.maxWidth / columns
val minColWidth = constraints.minWidth / columns
val placeables = measurables.mapIndexed { index, measurable ->
val column = index % columns
//RIGHT HERE .. is this OK, or should I restrict the height constraints too,
// based on the row that this item will be placed in, and the height of previously
// measured rows?
val cellConstraints = constraints.copy(minWidth = minColWidth, maxWidth = maxColWidth)
}
layout() {}
}
}
Grid
composable with 3 columns and some modifiers such that the maxHeight constraint is 1000, and the measureables list contains 12 items. I’m going to end up with 4 rows.
Let’s say that all my items are roughly the same height, of 300. So, the first 3 rows will end up taking up 900 px of space, leaving only 100 for the last row. When I’m measuring the items to go in the last row, do I need to pass in 100 as the maxHeight constraint to the measure function on those items … Or can I leave it off (and if so, I presume that would just cause the items to get clipped when the ui is rendered?).Zach Klippenstein (he/him) [MOD]
11/04/2021, 4:29 PMBradleycorn
11/04/2021, 6:04 PMa layout measures itself beyond its max constraints then it will automatically be cropped and centered in its parent.then I would measure the children without any further constraints, and use the sum of the row heights as the layout height. Or if I want:
a layout is also free to give whatever constraints it wants to its children and crop them or arrange them however it wants.then I would calculate and limit the height constraints when measuring the children, so they they all fit within the layout. Correct? I think for my grid I will go with a variation on the first option: … I’ll measure children without any further constraints, and then for the layout, I’ll use the sum of the row heights, but coerce that value to be within the bounds of the container constraints. If I understand everything correctly, that’ll result in a grid that is effectively laid out from top to bottom, and if the content is too tall, rows/items at the bottom will get clipped/cropped out. To me that makes the most sense for my use case. If I call:
Grid( columns = 3,
modifier = Modifier.height(40.dp)) {
(1..100).forEach { Text("Item $it") }
}
My expectation would be that it renders the first row or 2 and then clips somewhere in/around the 3rd row, since I set the height for the Grid to be 40.dp
. I think what I said above would accomplish that. I would NOT want it show show me some middle section of the list (because I did the layout pass with a huge height), or make each Text get clipped to a super tiny size (because I limited the height of each child so that they would all fit within the 40.dp limit).
I’ll play around with it and see what I get.Zach Klippenstein (he/him) [MOD]
11/04/2021, 6:05 PMlayout()
function in the MeasurePolicy
. If that value is outside the max constraints, then it gets cropped and centered. But the layout can also measure its children with larger constraints, then measure itself as max constraints (so it has control over its own cropping/alignment in parent), and place its children however it wants.Bradleycorn
11/04/2021, 6:08 PM//measure all the measurables, then
val layoutHeight = constraints.constrainHeight(rowHeights.sum())
layout(width, layoutHeight) {
//place the children
}
constrainHeight
basically is the same as rowHeights.sum().coerceAtMost(constraints.maxHeight)
)Zach Klippenstein (he/him) [MOD]
11/04/2021, 6:11 PMBradleycorn
11/04/2021, 7:57 PM