I am working on Jetpack Compose Navigation demo and I have a nested navigation graph with two different nested routes and screens for each nested route:
Login Graph has three routes for display three different Screens
Main Graph has two routes for these screens
The nested graph creation is called in the MainActivity.kt
setContent {
NavigationDemoTheme {
val navController = rememberNavController()
SetupNavGraph(navController = navController)
}
}
The function in the file NestedNavGraph.kt looks like this:
fun SetupNavGraph(navController: NavHostController) {
NavHost(navController = navController, startDestination = "login_route")
{
loginGraph(navController = navController)
mainGraph(navController = navController)
}
}
In the file LoginNavGraph.kt I have defined the routes and start destination
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login", route = "login_route") {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
In the file MainNavGraph.kt I have defined these two routes and this start destination:
navigation(startDestination = "home", route = "main_route") {
composable(route = "home") {
HomeScreen(navController = navController)
}
composable(route = "settings") {
SettingsScreen(navController = navController)
}
}
My questions now is: How can I display the RecoverPasswordScreen from SettingsScreen. I know I can navigate to the "login_route" from the SettingsScreen with but then the startDestination will be displayed, which is the LoginScreen.
// shows the LoginScreen because the startDestination in the "login_route" is set to "login"
navController.navigate(route = "login_route")
So, how can I directly navigate to the route "recover" in the nested graph route "login_route"? The following "workarounds" are in my mind:
Pass a parameter to the "login_route", for example something with:
navController.navigate(route = "login_route?destination=recover")
I will then have only a single route as a destination, for example "LoginView". This will change the loginGraph like this:
fun NavGraphBuilder.loginGraph(navController: NavController) {
navigation(startDestination = "login_view, route = "login_route/{destination}) {
composable(
route = "login_view",
arguments = listOf(
navArgument("destination") { defaultValue = "login" },
)
) { backStackEntry ->
val destination = backStackEntry.arguments?.getString("destination");
destination?.let { destination ->
LoginView(destination = destination)
}
}
}
}
The LoginView is composable whichw will have a own NavHost where I can set the startDestination with the query parameter from the previous route:
fun LoginView( destination : String = "login"){
val navController = rememberNavController()
var startDestination = destination;
Scaffold ()
{
NavHost(
navController = navController,
startDestination = startDestination
) {
composable(route = "login") {
LoginScreen(navController = navController)
}
composable(route = "register") {
RegisterScreen(navController = navController)
}
composable(route = "recover") {
RecoverPasswordScreen(navController = navController)
}
}
}
Now I should be able to call the RecoverPasswordScreen from the SettingsScreen with this:
navController.navigate(route = "login_route?destination=recover")
Another possibility is to have extra route for the RecoverPassword Screen in the MainGraph defined. Is there any other possibilty to directly acess a route in a nested graph? It would be great if could dynamically change startDestination when routing to "login_route" but I don't know how or if this is even possible.
A possible solution is to use deeplinks defined in the navigation graph - they also work for nested destinations. Then, instead of navigating to the route name, you can use navController.navigate(deepLinkUri)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With