-
I'm working with this composable function to create a ChildStack: @Composable
inline fun <reified C : Parcelable> ChildStack(
modifier: Modifier = Modifier,
source: StackNavigationSource<C>,
noinline initialStack: () -> List<C>,
key: String = "DefaultChildStack",
handleBackButton: Boolean = false,
animation: StackAnimation<C, ComponentContext>? = null,
noinline content: @Composable (C) -> Unit,
) {
val componentContext = LocalComponentContext.current
Children(
stack = remember {
componentContext.childStack(
source = source,
initialStack = initialStack,
key = key,
handleBackButton = handleBackButton,
childFactory = { _, childComponentContext -> childComponentContext },
)
},
modifier = modifier,
animation = animation,
) { child ->
ProvideComponentContext(child.instance) {
content(child.configuration)
}
}
} Basically my layout looks like this: Scaffold(
modifier = Modifier.background(color = MaterialTheme.colors.background),
scaffoldState = scaffoldState,
topBar = {
TopAppBar()
},
bottomBar = {
BottomNavigation() {
listOf(
TabItem.Dashboard,
TabItem.Second,
TabItem.Third,
).forEach { tabItem ->
BottomNavigationItem(
icon = { ... },
label = { ... },
...
)
}
}
},
) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
when (selectedTabItem) {
is TabItem.Dashboard -> {
val navigation = remember { StackNavigation<Screen>() }
ChildStack(
source = navigation,
initialStack = { listOf(Screen.Dashboard) },
key = "DashboardStack",
handleBackButton = true,
animation = stackAnimation { child ->
when (child.configuration) {
//is Screen.Catalog -> fade() + scale()
else -> slide()
}
},
) { screen ->
when (screen) {
is Screen.DashboardSubScreen -> {
/* Here I'd like to push all child screens */
DashboardSubScreen(navigate = { navigation.push(it) })
}
...
}
}
}
is TabItem.Second -> { ChildStack }
is TabItem.Third -> { ChildStack }
}
}
} @Composable
fun DashboardSubScreen(
navigate: (Screen) -> Unit,
) { ... } How can I have a ChildStack for each tab item? Thanks for your help in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
It looks like you are following the article A comprehensive thirty-line navigation for Jetpack/Multiplatform Compose The issue can be fixed by properly remembering the Child Stack, which can be done in different ways. You can choose what you like best.
Create the root import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.arkivanov.decompose.retainedComponent
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val rootComponentContext = retainedComponent { it }
// The rest of the code
}
} Define the following function: @Composable
inline fun <reified T> rememberRetained(factory: () -> T): T =
LocalComponentContext.current.instanceKeeper.getOrCreateSimple(
key = "RememberedRetainedInstance-$currentCompositeKeyHash",
factory = factory,
) Use the new
Define the following class: class RouterComponentContext(
componentContext: ComponentContext,
) : ComponentContext by componentContext {
val map: MutableMap<Any, Any?> = HashMap()
} Define val LocalComponentContext: ProvidableCompositionLocal<RouterComponentContext> =
staticCompositionLocalOf { error("Root component context was not provided") }
@Composable
fun ProvideComponentContext(componentContext: RouterComponentContext, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalComponentContext provides componentContext, content = content)
} Define the following functions: @Composable
inline fun <reified T> rememberInstance(factory: () -> T): T =
LocalComponentContext.current.map.getOrPut(
key = "RememberedInstance-$currentCompositeKeyHash",
defaultValue = factory,
) as T
@Composable
fun <C : Any> rememberStackNavigation(): StackNavigation<C> =
rememberInstance { StackNavigation() }
@Composable
inline fun <reified C : Parcelable> ChildStack(
source: StackNavigationSource<C>,
noinline initialStack: () -> List<C>,
modifier: Modifier = Modifier,
key: String = "DefaultChildStack",
handleBackButton: Boolean = false,
animation: StackAnimation<C, RouterComponentContext>? = null,
noinline content: @Composable (C) -> Unit,
) {
val componentContext = LocalComponentContext.current
Children(
stack = rememberInstance {
componentContext.childStack(
source = source,
initialStack = initialStack,
key = key,
handleBackButton = handleBackButton,
childFactory = { _, childComponentContext -> RouterComponentContext(childComponentContext) },
)
},
modifier = modifier,
animation = animation,
) { child ->
ProvideComponentContext(child.instance) {
content(child.configuration)
}
}
} Now use the new functions instead.
|
Beta Was this translation helpful? Give feedback.
It looks like you are following the article A comprehensive thirty-line navigation for Jetpack/Multiplatform Compose
. There is a known issue in the article - nested navigation is not working. Unfortunately, I did not have free time to update the article.
The issue can be fixed by properly remembering the Child Stack, which can be done in different ways. You can choose what you like best.
InstanceKeeper
.Create the root
ComponentContext
as follows: