Issue
I have connected my menu xml and the Android Navigation Components via navigation_view.setupWithNavController(navController)
and everything is working perfectly. Part of my menu is the Logout option. If the user selects this navigation destination, the app should navigate to the AuthorizationFragment
and pop the backstack to this Fragment with inclusive set to true to remove all previous fragments.
I looked into the code of the navigation library and reached the point where this should happen:
NavigationUI.onNavDestinationSelected():
/**
* Attempt to navigate to the {@link NavDestination} associated with the given MenuItem. This
* MenuItem should have been added via one of the helper methods in this class.
*
* <p>Importantly, it assumes the {@link MenuItem#getItemId() menu item id} matches a valid
* {@link NavDestination#getAction(int) action id} or
* {@link NavDestination#getId() destination id} to be navigated to.</p>
* <p>
* By default, the back stack will be popped back to the navigation graph's start destination.
* Menu items that have <code>android:menuCategory="secondary"</code> will not pop the back
* stack.
*
* @param item The selected MenuItem.
* @param navController The NavController that hosts the destination.
* @return True if the {@link NavController} was able to navigate to the destination
* associated with the given MenuItem.
*/
public static boolean onNavDestinationSelected(@NonNull MenuItem item,
@NonNull NavController navController) {
NavOptions.Builder builder = new NavOptions.Builder()
.setLaunchSingleTop(true)
.setEnterAnim(R.anim.nav_default_enter_anim)
.setExitAnim(R.anim.nav_default_exit_anim)
.setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
.setPopExitAnim(R.anim.nav_default_pop_exit_anim);
if ((item.getOrder() & Menu.CATEGORY_SECONDARY) == 0) {
builder.setPopUpTo(findStartDestination(navController.getGraph()).getId(), false);
}
NavOptions options = builder.build();
try {
//TODO provide proper API instead of using Exceptions as Control-Flow.
navController.navigate(item.getItemId(), null, options);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
So my question is, whether there is a way to override this method and to build NavOptions that are popping the backstack to the destination id with the inclusive option set to true?
Solution
As usual, sleeping over a problem helps. I found out that you can easily set your own NavigationItemSelectedListener
. Also the method I am mentioning in my question is public static, so it can also easily be called as fallback functionality.
Here's my code:
navigation_view.setNavigationItemSelectedListener { item: MenuItem ->
// check for my special case where I want to pop everything
// from the backstack until we reach the login fragment
if (item.itemId == R.id.fragment_auth) {
val options = NavOptions.Builder()
.setPopUpTo(navController.currentDestination!!.id, true)
.setLaunchSingleTop(true)
.build()
navController.navigate(R.id.action_global_authFragment, null, options)
true // return true -> we handled this navigation event
} else {
// Fallback for all other (normal) cases.
val handled = NavigationUI.onNavDestinationSelected(item, navController)
// This is usually done by the default ItemSelectedListener.
// But there can only be one! Unfortunately.
if (handled) drawer_layout.closeDrawer(navigation_view)
// return the result of NavigationUI call
handled
}
}
Answered By - muetzenflo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.