How can i set width of a group of composables, siblings layout from top to bottom, to width of longest one?
What i try to build is exactly same thing as in the images above. For simplicity let's say quote the component at the top and message box which contains message and another container that stores date and message status.
The longest one of quote and message box must be set as parent width and other one must be set to same width as longest one which requires a remeasuring for short one i assume.
Also if message box
gets to resized there needs to be an internal parameter that passes this width to set position of container that stores date and status. As can be seen clearly with bounds message text is moved to start while status to end when quote is longer than message box. When message has more than one line message box width and height are set with a calculation as telegram or whatsapp does.
Built this initially with Layout
as
@Composable
private fun DynamicLayout(
modifier: Modifier = Modifier,
quote: @Composable () -> Unit,
message: @Composable () -> Unit
) {
val content = @Composable {
quote()
message()
}
Layout(content = content, modifier = modifier) { measurables, constraints ->
val placeableQuote = measurables.first().measure(constraints)
val quoteWidth = placeableQuote.width
val placeableMessage =
measurables.last()
.measure(Constraints(minWidth = quoteWidth, maxWidth = constraints.maxWidth))
val messageWidth = placeableMessage.width
val maxWidth = quoteWidth.coerceAtLeast(messageWidth)
val totalHeight = placeableQuote.height + placeableMessage.height
layout(maxWidth, totalHeight) {
placeableQuote.placeRelative(x = 0, y = 0)
placeableMessage.placeRelative(x = 0, y = placeableQuote.height)
}
}
}
Where i measure message box using width of quote constraint it works but only when quote is longer.
DynamicLayout(
quote = {
Text(
"QUOTE with a very long text",
modifier = Modifier
.background(Color(0xffF44336))
.height(60.dp),
color = Color.White
)
},
message = {
Text(
"MESSAGE Content",
modifier = Modifier
.background(Color(0xff9C27B0)),
color = Color.White
)
}
)
DynamicLayout(
quote = {
Text(
"QUOTE",
modifier = Modifier
.background(Color(0xffF44336))
.height(60.dp),
color = Color.White
)
},
message = {
Text(
"MESSAGE with very long Content",
modifier = Modifier
.background(Color(0xff9C27B0)),
color = Color.White
)
}
)
As it's must be remeasured i think solution for this question should be done with SubComposeLayout
but couldn't figure out how to use it for this setup?
@Composable
private fun SubComponentLayout(
modifier: Modifier = Modifier,
mainContent: @Composable () -> Unit,
dependentContent: @Composable (Int) -> Unit
) {
SubcomposeLayout(modifier = modifier) { constraints ->
val mainMeasurables: List<Measurable> = subcompose(SlotsEnum.Main, mainContent)
val mainPlaceables: List<Placeable> = mainMeasurables.map {
it.measure(constraints)
}
val maxSize =
mainPlaceables.fold(IntSize.Zero) { currentMax: IntSize, placeable: Placeable ->
IntSize(
width = maxOf(currentMax.width, placeable.width),
height = maxOf(currentMax.height, placeable.height)
)
}
var maxWidth =
mainPlaceables.maxOf { it.width }
layout(maxSize.width, maxSize.height) {
println(" SubcomposeLayout-> layout() maxSize width: ${maxSize.width}, height: ${maxSize.height}")
val dependentMeasurables: List<Measurable> = subcompose(
slotId = SlotsEnum.Dependent,
content = {
println(" SubcomposeLayout-> layout()->subcompose() mainWidth ZERO")
dependentContent(0)
}
)
val dependentPlaceables: List<Placeable> = dependentMeasurables.map {
it.measure(constraints)
}
maxWidth = maxWidth.coerceAtLeast(
dependentPlaceables.maxOf { it.width }
)
subcompose(SlotsEnum.NEW) {
println(" SubcomposeLayout-> layout()->subcompose() maxWidth: $maxWidth")
dependentContent(maxWidth)
}
mainPlaceables.forEach { it.placeRelative(0, 0) }
dependentPlaceables.forEach { it.placeRelative(0, 150) }
}
}
}
Why cannot remeasure same component second time with same id? When i try to call subCompose
with SlotsEnum.Dependent it throws an exception
subcompose(SlotsEnum.NEW) {
println(" SubcomposeLayout-> layout()->subcompose() maxWidth: $maxWidth")
dependentContent(maxWidth)
}
Still not remeasuring correctly after calling it? How can setting sibling can be solved with SubcomposeLayout
?