[英]Using Navigation Architecture Component with Navigation Drawer
我正在尝试将导航架构组件(NavHostFragment) 与导航抽屉(widget.NavigationView) 一起使用。 我收到以下两个错误之一。
1) 多次从抽屉中选择物品时可能会发生这种情况:
java.lang.IllegalArgumentException: navigation destination app.myDomain.navdrawertrials:id/action_rootFragment_to_settingsFragment is unknown to this NavController
2)这发生在我的真实代码库中,该代码库的设置方式与 AFAICT 下面的简化示例相同。 为什么不设置当前导航节点?
java.lang.IllegalStateException: no current navigation node
简化代码
主要活动
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>
导航图.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(其他节点都是类似的空片段,只有一个标签)
<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>
关于第一个错误,根据您的代码,当用户从抽屉中选择“第一个”或“设置”时,他将使用action_rootFragment_to_firstFragment
或action_rootFragment_to_settingsFragment
操作转移到“第一个”或“设置”片段,但如果您尝试再次选择“第一个”或抽屉中的“设置”,导航图中的firstFragment
或settingsFragment
元素中没有action_rootFragment_to_firstFragment
或action_rootFragment_to_settingsFragment
操作。
解决方法是改变:
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)
}
到:
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)
}
更好的解决方案是将目的地绑定到菜单驱动的 UI 组件(在您的案例抽屉中),将您的菜单项 ID 更改为与目的地 ID 相同,如下所示:
<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" />
并添加
setupWithNavController(nav_view, navController )
在你的主要活动中,而不是
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
}
2) 如果在方向改变时发生碰撞。 使用下面的活动升级导航版本模块到2.2.0或以上
implementation "androidx.navigation:navigation-fragment-ktx:2.2.0"
implementation "androidx.navigation:navigation-ui-ktx:2.2.0"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.