Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Navigation graph with multiple top level destinations

Tags:

I am implementing an android app (in Kotlin, but that is not relevant to the Problem) in my free time and I try to use android jetpack and new libraries. I have a single Activity with a navigation drawer. I try to follow the sample sunflower app. It uses the following combination in the main activity to enable the logic behind the navigation drawer:

appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout) setSupportActionBar(findViewById(R.id.toolbar)) setupActionBarWithNavController(navController, appBarConfiguration) 

Note on this code: This automatically will navigate to the correct fragments when clicked in the navigation drawer and close the drawer and keep them selected etc. All that boilerplate code. That is pretty neat and also works. As far as I understand this, the IDs of the navigation drawer menu items have to match the ids of the fragments in the navigation graph and this way they are connected.

The problem I have: When I use the navigation drawer to go to any fragment other than the starting fragment of the navigation graph, it will display a back button instead of the hamburger item. That is not what I expect, I would expect it still to be the hamburger item since the navigation drawer is for navigating between views on an equal level and not nested in each other, right? I expect a back button if I navigate to a subfragment of any fragment by clicking on elements in that fragment (for example list -> detail) but not if I navigate using the navigation drawer.

Now I traced that problem back to the AppBarConfiguration builder which reads on the constructor taking a navgraph The NavGraph whose start destination should be considered the only top level destination. I can fairly easily fix that by overriding AppBarConfiguration to return different top level destinations than just the starting destination of the navigation graph.

However my question is, why is there this behaviour default? Is it a bug? If I override this will I violate some design guidelines by Google? Should not every element in the navigation drawer be on the same level how I expect it? Is there a different solution intended for what I want to do?

like image 529
findusl Avatar asked Nov 19 '18 10:11

findusl


People also ask

What is popUpTo and popUpToInclusive?

When navigating back to destination A, we also popUpTo A, which means that we remove B and C from the stack while navigating. With app:popUpToInclusive="true" , we also pop that first A off of the stack, effectively clearing it.

What is launchSingleTop?

launchSingleTop. var launchSingleTop: Boolean. Whether this navigation action should launch as single-top (i.e., there will be at most one copy of a given destination on the top of the back stack). This functions similarly to how android. content.

What is onSupportNavigateUp?

onSupportNavigateUp() This method is called whenever the user chooses to navigate Up within your application's activity hierarchy from the action bar.


2 Answers

You don't have to override AppBarConfiguration. Since version alpha7 AppBarConfiguration has a constructor with a set of ids for all top level destinations.

Set<Integer> topLevelDestinations = new HashSet<>(); topLevelDestinations.add(R.id.fragment1); topLevelDestinations.add(R.id.fragment2); appBarConfiguration = new AppBarConfiguration.Builder(topLevelDestinations)                                              .setDrawerLayout(drawerLayout)                                              .build(); NavigationUI.setupActionBarWithNavController(this,                                               this.navController,                                              this.appBarConfiguration); 

This is not default as the navigation graph has only a single start fragment which should always be the single entry point of the application.

Editing the default behavior with AppBarConfiguration does not make it behave as before, every top level fragment is placed on the back stack so back button will go to all top level fragments. It is unclear how I can make top level fragments as the first element of the back stack.

like image 119
Elias DC Avatar answered Sep 21 '22 18:09

Elias DC


I made simple example for this issue. https://github.com/isaul32/android-sunflower

Create set of top level destinations at first

val topLevelDestinations = setOf(R.id.garden_fragment,         R.id.plant_list_fragment) appBarConfiguration = AppBarConfiguration.Builder(topLevelDestinations)         .setDrawerLayout(drawerLayout)         .build() 

and then override onSupportNavigateUp function like this

override fun onSupportNavigateUp(): Boolean {     return NavigationUI.navigateUp(navController, appBarConfiguration) } 
like image 43
iSaul Avatar answered Sep 22 '22 18:09

iSaul