I am using the Navigation Component, currently I have two graphs, the first one has an activity that shows the login screen and the registration screen, and from the login screen I navigate to a second graph with another activity that contains a navigation bar. The problem I have is that when I navigate from graph A to graph B, it's like it only shows me the content of what the loaded fragment of graph B would have, but it doesn't show the navigation bar:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph_home"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.ludiras.ameisin.ui.home.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" >
<action
android:id="@+id/action_homeFragment2_to_profileFragment2"
app:destination="@id/profileFragment2" />
</fragment>
<fragment
android:id="@+id/profileFragment2"
android:name="com.ludiras.ameisin.ui.profile.view.ProfileFragment"
android:label="fragment_profile"
tools:layout="@layout/fragment_profile" />
</navigation>
This is the method I use to navigate to the second graph:
private fun setupObservers() {
viewModel.getEmailRegisterLiveData().observe(viewLifecycleOwner, Observer {
val action = LoginFragmentDirections.actionLoginFragmentToHomeNavGraph()
findNavController().navigate(action)
})
}
And in the first graph I have, in addition to the include with said graph, this action which is what allows me to navigate:
<fragment
android:id="@+id/loginFragment"
android:name="com.ludiras.ameisin.ui.login.view.LoginFragment"
android:label="fragment_login"
tools:layout="@layout/fragment_login">
<action
android:id="@+id/actionLoginFragmentToHomeNavGraph"
app:destination="@id/nav_graph_home" />
<action
android:id="@+id/actionLoginFragmentToRegisterFragment"
app:destination="@id/registerFragment"
app:popUpTo="@id/loginFragment"
app:popUpToInclusive="true" />
</fragment>
The other solution I had thought of was to implement just one activity with only a graph and show and hide the bar where I need it, but I want to know if it is possible the way I am doing it with two graphs.
Explanation
Your mistake is believing that each graph is associated with a different activity, when in reality there is no relationship between them. When you navigate to the
homeFragment
, you are still in the first activity and so the content of the second activity is not displayed.Activities have a
NavHost
that is associated with aNavController
. We can say that each activity has a navController (it actually has one for each navHost). Now theNavGraph
one using this controller is something dynamic. Initially it is the one defined in the attributeapp:navGraph
of its associated host but if you want you can change it at any time with thenavController.setGraph(R.id.otherGraph)
. In turn, the same graph can be used by several controllers at the same time, or by none.Solution
If you want to navigate to another activity, you must add it to your graph and treat it as another destination.
But you should know that the navController can't close activities, so you'll have to take care of that manually.
Recommended Solution
The recommended solution is the last one you mentioned: have a single activity and show or hide the navigation bar accordingly. What you can do with the method
addOnDestinationChangedListener
Another important thing that you should change is that, regardless of the option you choose, the start destination should be
fragment_home
y redirect tologinFragment
when the user is not logged in. Example in the documentation . In this way you respect the principle of the fixed start destination and also speed up the loading of your application for the most frequent case, which should be when the user is logged in.new alternative
Following the line of a single activity, there is a new alternative that I will only briefly mention so as not to extend the answer further.
I'm not sure what you're calling a "navigation bar" (could be navigation drawer, navigation rail, bottom navigation or app bar) but all those components have a composable implementation . The advantage of using this implementation is its infinite flexibility that goes far beyond simply hiding or showing. Thanks to this, it is very easy to create, for example, a composable appBar that has different actions in each destination or create custom animations like this that are not possible with a view-based implementation. If you choose this alternative, you will probably also want to integrate the new artifact navigation-compose for more consistency.
conclusion
A
NavGraph
is simply an array ofNavDestination
s. Having multiple nests is technically the same as having just one. You should not think that each graph is associated with a different activity. Nested graphs exist simply for better organization and so that you can reuse them in anotherNavController
. Even if you choose the two activities option, you don't need to have two graphs . Separate them only if you think it convenient.