I would like to implement an onboarding process using a parent Composable
showing the current step (e.g. “1 from 5”). The parent knowns nothing about the children, triggering the progress updates (I can not change the existing app architecture). The progress update also has to work on back navigation (e.g. from step 3 to step 2).
My current take to solve this problem is using a singleton of an MutableStateFlow
for the current step, which is injected in the parent and the corresponding children. The progress state is set by the children during the composition. This seems to work, but changing the state of the parent during the composition of it’s children feels not the right way to go.
Do you have a better idea?
If parent’s not knowing about its content is a requirement you can create scope such as
content: @Composable ((Int) -> Unit) -> Unit
instead of
content: @Composable (() -> Unit) -> Unit
You can refer this answer for similar requirement, this basically allows children to trigger event on parent without knowing anything about each others layout or params.
In example ColumnScope extension is for demonstration, it can be any ui Composable scope or no scope at all.
@Composable
fun Parent(
content: @Composable ColumnScope.((Int) -> Unit) -> Unit,
) {
var currentIndex by remember {
mutableStateOf(0)
}
val lambda: (Int) -> Unit = remember {
{ value ->
currentIndex = value
}
}
Column(modifier = Modifier.fillMaxSize()) {
Text("Current Progress: $currentIndex")
content(lambda)
}
}
Usage
@Preview
@Composable
fun TestLamdaPass() {
Parent { result: (Int) -> Unit ->
Button(
onClick = {
result.invoke(0)
}
) {
Text("Some Text")
}
Button(
onClick = {
result.invoke(1)
}
) {
Text("Some Text")
}
Button(
onClick = {
result.invoke(2)
}
) {
Text("Some Text")
}
}
}