We have a legacy app that we start migrating to Jetpack Compose. The app has a single activity, uses Navigation component with a navigation XML graph to navigate between fragments.
We are following this approach:
Now, say we had Fragment1 containing some action to navigate to Fragment2. In the original code we would call the following in Fragment1:
NavHostFragment.findNavController(this).navigate(directionToFragment2)
When creating a composable to replace Fragment1 UI, how can we implement the navigation from this composable to Fragment2? In the composable we can call:
val navController = rememberNavController()
But this seems to be a different navigation controller than the one used by the fragments. Is there a way from a composable to get access to the same navigation controller as the one used by the fragment?
The only alternative we currently see is to pass the Fragment's navigation controller as a parameter to the composable, but it doesn't look quite right.
You are correct that you cannot use rememberNavController()
- that will create a completely new nested NavController
suitable only for composable destinations.
As per the testing guide, it is strongly recommended to avoid any direct references to any NavController
within any of your composables themselves (i.e., a HomeScreen
composable). Instead, the recommendation is to pass in a lambda that your composable can trigger when it wants to navigate.
Your Fragment (the one calling setContent
on your ComposeView
) would then be responsible for implementing that lambda and calling NavHostFragment.findNavController(this).navigate(directionToFragment2)
.
As a (less recommended) alternative, you can also use LocalView.current.findNavController()
as Fragments populate the NavController
at the view level as well and LocalView
points to the ComposeView
hosting your Composable.