Ben Abramovitch
06/30/2021, 10:59 PMTash
06/30/2021, 11:23 PMBen Abramovitch
06/30/2021, 11:24 PMBen Abramovitch
06/30/2021, 11:24 PMTash
06/30/2021, 11:25 PMBen Abramovitch
06/30/2021, 11:25 PMTash
06/30/2021, 11:59 PMwidth = totalWidth in your layout, (0,0) is actually offscreen, and what you need is almost a translation of the “canvas” to bring 0,0 to the top-left of the visible windowTash
06/30/2021, 11:59 PMAlignmentLine, how’d that go?Ben Abramovitch
07/01/2021, 12:04 AMBen Abramovitch
07/01/2021, 12:04 AMBen Abramovitch
07/01/2021, 12:12 AMpackage androidx.compose.ui.layout
fun layout(
width: Int,
height: Int,
alignmentLines: Map<AlignmentLine, Int> = emptyMap(),
placementBlock: Placeable.PlacementScope.() -> Unit
) = object : MeasureResult {
override val width = width
override val height = height
override val alignmentLines = alignmentLines
override fun placeChildren() {
Placeable.PlacementScope.executeWithRtlMirroringValues(
width,
layoutDirection,
placementBlock
)
}
}
}Ben Abramovitch
07/01/2021, 12:14 AMAdam Powell
07/01/2021, 12:44 AMBen Abramovitch
07/01/2021, 12:45 AMAdam Powell
07/01/2021, 12:45 AMAdam Powell
07/01/2021, 12:45 AMconstraints.maxWidth in that codeBen Abramovitch
07/01/2021, 12:51 AMconstraints.copy(
minWidth = headerWidth,
maxWidth = headerWidth,
minHeight = height,
maxHeight = height,
)Ben Abramovitch
07/01/2021, 12:55 AMLayout(
modifier = Modifier.fillMaxWidth(),
content = {
columnList.forEach { header ->
Box {
headerContent(header)
}
}
},
)Ben Abramovitch
07/01/2021, 12:55 AMheaderContent: @Composable (title: String) -> Unit = { title ->
Text(title, modifier = Modifier.fillMaxWidth())
},Adam Powell
07/01/2021, 1:04 AMlayout(width = totalWidth, height = height) {
and those are calculated as
val height = 45.dp.roundToPx()
val totalWidth = headerWidth * numberOfHeaders
both of which completely ignore the incoming constraintsAdam Powell
07/01/2021, 1:05 AMlayout must be in range of the constraints, if you violate that, your measurable gets clamped to the constraints and your placement is centered in the clamped space where your parent placed youBen Abramovitch
07/01/2021, 1:05 AMAdam Powell
07/01/2021, 1:06 AM) { measureables, constraints ->Ben Abramovitch
07/01/2021, 1:06 AMAdam Powell
07/01/2021, 1:06 AMBen Abramovitch
07/01/2021, 1:06 AMAdam Powell
07/01/2021, 1:07 AMBen Abramovitch
07/01/2021, 1:09 AMLayout(
modifier = Modifier.fillMaxWidth(headerWidth * numberOfHeaders.toFloat()).fillMaxHeight(100f),
content = {
columnList.forEach { header ->
Box {
headerContent(header)
}
}
}
)
This doesn’t work either (i changed height to also be 100 further below)Ben Abramovitch
07/01/2021, 1:12 AMBen Abramovitch
07/01/2021, 1:15 AM@Composable
fun HeaderTest(
columnList: List<String>,
headerWidth: Dp,
headerContent: @Composable (title: String) -> Unit = { title ->
Text(title, modifier = Modifier.fillMaxWidth())
},
) {
val numberOfHeaders = columnList.count()
Layout(
modifier = Modifier
.width(headerWidth * numberOfHeaders)
.height(100.dp)
.fillMaxHeight()
.fillMaxWidth(),
content = {
columnList.forEach { header ->
Box {
headerContent(header)
}
}
}
) { measureables, constraints ->
val height = 100.dp
val totalWidth = headerWidth * numberOfHeaders
val placeWithHeader = measureables.map { measurable ->
val constraint = constraints.copy(
minWidth = headerWidth.roundToPx(),
maxWidth = headerWidth.roundToPx(),
minHeight = height.roundToPx(),
maxHeight = height.roundToPx()
)
measurable.measure(constraint)
}
layout(width = totalWidth.roundToPx(), height = height.roundToPx()) {
placeWithHeader.forEachIndexed { index, placeable ->
val offset = index * headerWidth.roundToPx()
placeable.place(offset, 0)
}
}
}
}Adam Powell
07/01/2021, 1:18 AMAdam Powell
07/01/2021, 1:20 AMval height = 100.dp.roundToPx().coerceIn(constraints.minHeight, constraints.maxHeight)
val totalWidth = (headerWidth * numberOfHeaders).coerceIn(constraints.minWidth, constraints.maxWidth)Ben Abramovitch
07/01/2021, 1:33 AMLayout(
modifier = modifier,
content = content
) { measurables, constraints ->
// Don't constrain child views further, measure them with given constraints
// List of measured children
val placeables = measurables.map { measurable ->
// Measure each children
measurable.measure(constraints)
}
But it also does the layout different….
// Set the size of the layout as big as it can
layout(constraints.maxWidth, constraints.maxHeight) {
Lots more reading to do, but this is why i’m starting sooner!Ben Abramovitch
07/01/2021, 1:34 AMBen Abramovitch
07/01/2021, 1:37 AMAdam Powell
07/01/2021, 1:37 AMAdam Powell
07/01/2021, 1:38 AMLayout composable influence but don't completely control the constraints your layout receivesAdam Powell
07/01/2021, 1:39 AMmeasurable.measure(constraints), it's calling the same kind of measuring code you're writing right now, but on the child elementAdam Powell
07/01/2021, 1:40 AMlayout(width, height) { function in that block, you're telling it the desired size of the Placeable that the measure call returnsAdam Powell
07/01/2021, 1:40 AMAdam Powell
07/01/2021, 1:41 AMAdam Powell
07/01/2021, 1:41 AMBen Abramovitch
07/01/2021, 1:42 AMBen Abramovitch
07/01/2021, 1:42 AMAdam Powell
07/01/2021, 1:43 AMBen Abramovitch
07/01/2021, 1:43 AMBen Abramovitch
07/01/2021, 1:44 AMBen Abramovitch
07/01/2021, 1:46 AM