I am trying to use the Navigation Architecture Component (NavHostFragment) with a Navigation Drawer (widget.NavigationView). I get one of the following two errors.
1) This can happen when selecting an item from the drawer several times:
java.lang.IllegalArgumentException: navigation destination app.myDomain.navdrawertrials:id/action_rootFragment_to_settingsFragment is unknown to this NavController
2) This happens from my real code base that is set up the same way as the simplified sample below AFAICT. Why would a current navigation node not be set?
java.lang.IllegalStateException: no current navigation node
Simplified Code
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
setupToolbar()
setupNavDrawer()
setupNavigation()
}
private fun setupToolbar() {
setSupportActionBar( toolbar )
}
private fun setupNavigation() {
val navController = findNavController( R.id.nav_host_fragment)
setupActionBarWithNavController( navController, main_activity_drawer_layout )
}
private fun setupNavDrawer() {
val toggle = ActionBarDrawerToggle(
this,
main_activity_drawer_layout,
toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close)
main_activity_drawer_layout.addDrawerListener(toggle)
toggle.syncState()
nav_drawer.setNavigationItemSelectedListener {
val navController = findNavController( R.id.nav_host_fragment )
when (it.itemId) {
R.id.nav_drawer_root_menu_item -> navController.navigate(R.id.rootFragment)
R.id.nav_drawer_first_menu_item -> navController.navigate(R.id.action_rootFragment_to_firstFragment)
R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment)
}
main_activity_drawer_layout.closeDrawer(GravityCompat.START)
true
}
}
override fun onSupportNavigateUp() = findNavController(R.id.nav_host_fragment).navigateUp()
}
main_activity.xml
<android.support.v4.widget.DrawerLayout
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/main_activity_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/main_activity_content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_drawer_header"
app:menu="@menu/nav_drawer_menu" />
</android.support.v4.widget.DrawerLayout>
nav_drawer_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/nav_drawer_root_menu_item"
android:title="To Root" />
<item
android:id="@+id/nav_drawer_first_menu_item"
android:title="To First" />
<item
android:id="@+id/nav_drawer_settings_menu_item"
android:title="To Settings" />
</menu>
main_activity_content.xml
<android.support.design.widget.CoordinatorLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true"
/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
nav_graph.xml
<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"
app:startDestination="@id/rootFragment">
<fragment
android:id="@+id/rootFragment"
android:name="app.anytune.navdrawertrials.RootFragment"
android:label="root_fragment"
tools:layout="@layout/root_fragment" >
<action
android:id="@+id/action_rootFragment_to_firstFragment"
app:destination="@id/firstFragment" />
<action
android:id="@+id/action_rootFragment_to_settingsFragment"
app:destination="@id/settingsFragment" />
</fragment>
<fragment
android:id="@+id/firstFragment"
android:name="app.anytune.navdrawertrials.FirstFragment"
android:label="first_fragment"
tools:layout="@layout/first_fragment" />
<fragment
android:id="@+id/settingsFragment"
android:name="app.anytune.navdrawertrials.SettingsFragment"
android:label="settings_fragment"
tools:layout="@layout/settings_fragment" />
</navigation>
root_fragment.xml (other nodes are similar empty fragments with just a label)
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RootFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Root Fragment" />
</FrameLayout>
To add a navigation drawer, first declare a DrawerLayout as the root view. Inside the DrawerLayout , add a layout for the main UI content and another view that contains the contents of the navigation drawer.
Regarding the first error, based on your code, when user select 'first' or 'settings' from drawer he is transferred to 'first' or 'settings' fragment using action_rootFragment_to_firstFragment
or action_rootFragment_to_settingsFragment
action, but if you try to select again 'first' or 'settings' from drawer there is no action_rootFragment_to_firstFragment
or action_rootFragment_to_settingsFragment
action inside firstFragment
or settingsFragment
element inside navigation graph.
The solution is to change:
when (it.itemId) {
R.id.nav_drawer_root_menu_item -> navController.navigate(R.id.rootFragment)
R.id.nav_drawer_first_menu_item -> navController.navigate(R.id.action_rootFragment_to_firstFragment)
R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment)
}
to:
when (it.itemId) {
R.id.nav_drawer_root_menu_item -> navController.navigate(R.id.rootFragment)
R.id.nav_drawer_first_menu_item -> navController.navigate(R.id.firstFragment)
R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.settingsFragment)
}
The better solution is to tie destinations to menu-driven UI components(in your case drawer), change your menu items id to same as destinations id's, like this:
<item
android:id="@+id/rootFragment"
android:title="To Root" />
<item
android:id="@+id/firstFragment"
android:title="To First" />
<item
android:id="@+id/settingsFragment"
android:title="To Settings" />
and add
setupWithNavController(nav_view, navController )
inside your main activity, instead of
nav_drawer.setNavigationItemSelectedListener {
val navController = findNavController( R.id.nav_host_fragment )
when (it.itemId) {
R.id.nav_drawer_root_menu_item -> navController.navigate(R.id.rootFragment)
R.id.nav_drawer_first_menu_item -> navController.navigate(R.id.action_rootFragment_to_firstFragment)
R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment)
}
main_activity_drawer_layout.closeDrawer(GravityCompat.START)
true
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With