Vivek Modi
05/25/2026, 4:25 PMSubcomposeLayout
The goal is to support:
• dynamic column sizing
• wrap-content + weighted columns
• consistent widths across rows
• flexible rendering based on available space
The current approach uses a multi-pass measurement flow:
1. measure wrap-content columns
2. Cache resolved widths
3. Distribute remaining width across weighted columns
4. perform final measurement/layout pass
Would love feedback on and open to any suggestions or improvements 🧵.Vivek Modi
05/25/2026, 4:27 PM@Composable
fun AdaptiveChecklistRowLayout(
layoutSpec: ChecklistLayoutSpec,
measuredWidths: SnapshotStateMap<ChecklistFieldKind, Int>,
modifier: Modifier = Modifier,
cell: @Composable (ChecklistFieldSpec) -> Unit,
) {
SubcomposeLayout(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
) { constraints ->
val columnSpacingPx = 24.dp.roundToPx()
val fields = layoutSpec.visibleFields
fields.forEach { field ->
val widthRule = field.widthRule
if (widthRule is FieldWidthRule.ContentBased) {
val minimumWidthPx = widthRule.minimumPx.dp.roundToPx()
val measuredWidth = subcompose("measure_${field.fieldKind}") {
cell(field)
}.first().measure(Constraints()).width
val resolvedWidth = maxOf(measuredWidth, minimumWidthPx)
val previousWidth = measuredWidths[field.fieldKind] ?: 0
if (resolvedWidth > previousWidth) {
measuredWidths[field.fieldKind] = resolvedWidth
}
}
}
val spacingWidth = ((fields.size - 1).coerceAtLeast(0)) * columnSpacingPx
var contentBasedWidth = 0
var totalFlexibleRatio = 0f
fields.forEach { field ->
when (val widthRule = field.widthRule) {
is FieldWidthRule.ContentBased -> {
contentBasedWidth += measuredWidths[field.fieldKind]
?: widthRule.minimumPx.dp.roundToPx()
}
is FieldWidthRule.Flexible -> {
totalFlexibleRatio += widthRule.ratio
}
}
}
val flexibleAvailableWidth =
(constraints.maxWidth - contentBasedWidth - spacingWidth).coerceAtLeast(0)
val safeRatioTotal = totalFlexibleRatio.coerceAtLeast(1f)
val cells = fields.map { field ->
val fieldWidth = when (val widthRule = field.widthRule) {
is FieldWidthRule.ContentBased -> {
measuredWidths[field.fieldKind]
?: widthRule.minimumPx.dp.roundToPx()
}
is FieldWidthRule.Flexible -> {
((widthRule.ratio / safeRatioTotal) * flexibleAvailableWidth).toInt()
}
}.coerceAtLeast(0)
subcompose("layout_${field.fieldKind}") {
cell(field)
}.first().measure(
Constraints.fixedWidth(fieldWidth),
)
}
val rowHeight = cells.maxOfOrNull { it.height } ?: 0
layout(
width = constraints.maxWidth,
height = rowHeight,
) {
var currentX = 0
cells.forEach { cellPlaceable ->
cellPlaceable.placeRelative(
x = currentX,
y = 0,
)
currentX += cellPlaceable.width + columnSpacingPx
}
}
}
}Oleksandr Balan
05/25/2026, 6:41 PMVivek Modi
05/25/2026, 7:08 PMVivek Modi
05/25/2026, 7:08 PMOleksandr Balan
05/25/2026, 7:44 PMAlex Vanyo
05/26/2026, 11:21 PMSubcomposeLayout to build a layout is one of the more expensive ways to do it - it'll work, but it requires deferring all of the composition work for the children until measurement.
The new Grid should be exactly what you're looking for here