As can be seen in official documents there is layout named SubcomposeLayout defined as
Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.
Possible use cases:
You need to know the constraints passed by the parent during the composition and can't solve your use case with just custom Layout or LayoutModifier. See androidx.compose.foundation.layout.BoxWithConstraints.
You want to use the size of one child during the composition of the second child.
You want to compose your items lazily based on the available size. For example you have a list of 100 items and instead of composing all of them you only compose the ones which are currently visible(say 5 of them) and compose next items when the component is scrolled.
I searched Stackoverflow with SubcomposeLayout
keyword but couldn't find anything about it, created this sample code, copied most of it from official document, to test and learn how it works
@Composable
private fun SampleContent() {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
SubComponent(
mainContent = {
Text(
"MainContent",
modifier = Modifier
.background(Color(0xffF44336))
.height(60.dp),
color = Color.White
)
},
dependentContent = {
val size = it
println("π€ Dependent size: $size")
Column() {
Text(
"Dependent Content",
modifier = Modifier
.background(Color(0xff9C27B0)),
color = Color.White
)
}
}
)
}
}
@Composable
private fun SubComponent(
mainContent: @Composable () -> Unit,
dependentContent: @Composable (IntSize) -> Unit
) {
SubcomposeLayout { constraints ->
val mainPlaceables = subcompose(SlotsEnum.Main, mainContent).map {
it.measure(constraints)
}
val maxSize = mainPlaceables.fold(IntSize.Zero) { currentMax, placeable ->
IntSize(
width = maxOf(currentMax.width, placeable.width),
height = maxOf(currentMax.height, placeable.height)
)
}
layout(maxSize.width, maxSize.height) {
mainPlaceables.forEach { it.placeRelative(0, 0) }
subcompose(SlotsEnum.Dependent) {
dependentContent(maxSize)
}.forEach {
it.measure(constraints).placeRelative(0, 0)
}
}
}
}
enum class SlotsEnum { Main, Dependent }
It's supposed to re-measure a component based on another component size but what this code actually does is a mystery to me.
- How does
subcompose
function work? - What's the point of
slotId
and can we get slotId in a way?
The description for subCompose
function
Performs subcomposition of the provided content with given slotId. Params: slotId - unique id which represents the slot we are composing into. If you have fixed amount or slots you can use enums as slot ids, or if you have a list of items maybe an index in the list or some other unique key can work. To be able to correctly match the content between remeasures you should provide the object which is equals to the one you used during the previous measuring. content - the composable content which defines the slot. It could emit multiple layouts, in this case the returned list of Measurables will have multiple elements.
Can someone explain what it means or/and provide a working sample for SubcomposeLayout
?
mainComponent
but max of those 2composables
? I need an example to get longest of two composables then setting width of short one same as long one. How can i achieve this withSubcomposeLayout
? β Krenn