Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack Compose Navigation: Direct navigation to route in a nested graph which is not startDestination

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
  • Main Graph

Login Graph has three routes for display three different Screens

  • Route "login" for displaying LoginScreen
  • Route "register" for displaying RegisterScreen
  • Route "recoverPassword" for displaying RecoverPasswordScreen

Main Graph has two routes for these screens

  • Route "home" for displaying HomeScreen
  • Route "settings" for displaying SettingsScreen

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.

like image 791
xshake Avatar asked Dec 09 '25 15:12

xshake


1 Answers

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)

like image 189
Derek K Avatar answered Dec 11 '25 10:12

Derek K