Skip to content

Instantly share code, notes, and snippets.

@viperwarp
Last active June 7, 2018 04:27
Show Gist options
  • Save viperwarp/fbf275830d626c24761586cef5c53a57 to your computer and use it in GitHub Desktop.
Save viperwarp/fbf275830d626c24761586cef5c53a57 to your computer and use it in GitHub Desktop.
import android.annotation.SuppressLint
import android.support.design.widget.NavigationView
import android.support.v4.widget.DrawerLayout
import android.view.MenuItem
import androidx.navigation.NavController
import androidx.navigation.NavOptions
/**
* @author https://github.com/viperwarp
*
* An OnNavigationItemSelectedListener made to work with Android Navigation Components when
* you need to navigate between top level destinations using a Drawer style navigation menu.
*
* This listener must be set after calling {@code setupWithNavController(navController)} to replace
* the listener that the Navigation Components add.
*
* Known Issues:
* - When rotating or deep linking, the NavGraph is reloaded and reverts to the default startingDestination.
* - I don't know if there's any issue with retaining the NavigationView or the NavController here, YMMV.
* - This doesn't support navigating between peer views that are not top level Destinations
*
* Example Usage:
* <pre>
* {@code
* nav_view.setupWithNavController(navController)
* nav_view.setNavigationItemSelectedListener(NavMenuItemSelectedListener(nav_view, navController) {
* if (it.itemId == R.id.nav_logout) {
* onLogout()
* }
* drawer_layout.closeDrawer(GravityCompat.START)
* true
* })
* }
* </pre>
*
* @param navigationView the menu view
* @param navController navigation controller for the current NavGraph
* @param onNoDestination fallback for handling menu items that don't link to a destination
*
*/
class NavMenuItemSelectedListener(private val navigationView: NavigationView,
private val navController: NavController,
private val onNoDestination: (item: MenuItem) -> Boolean): NavigationView.OnNavigationItemSelectedListener {
@SuppressLint("ResourceType")
override fun onNavigationItemSelected(item: MenuItem): Boolean {
if (navController.graph.findNode(item.itemId) != null) {
navController.graph.startDestination = item.itemId // <- The Magic Sauce
val options = with(NavOptions.Builder()) {
setPopUpTo(R.navigation.my_nav_graph, true)
build()
}
navController.navigate(item.itemId, null, options)
val parent = navigationView.parent
if (parent is DrawerLayout) {
parent.closeDrawer(navigationView)
}
return true
}
return onNoDestination.invoke(item)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment