有一种场景,NavigationRailView + fragment + Navigation ,通过 findNavController().navigate() 跳转至DetailFragment,点击NavigationRailView 其他标签,再点回上一次的标签,此时标签未被选中,显示的页面为之前操作跳转的DetailFragment。必须在DetailFragment 中 调用 findNavController().popBackStack() 返回,标签才会被选中。如何在NavigationRailView 标签点击时,每次都显示当前标签下的首页fragment???
2022-12-15 更新
通过反复试验 可以使用 findNavController().clearBackStack() 在切换新的fragment 里 将之前的fragment 清除
override fun onAttach(context: Context) {
super.onAttach(context)
findNavController().clearBackStack(R.id.VideoFragment)
}
原理待分析,暂且解决了我的问题吧。。。
2023-04-23 再次更新,终极解决方案;
借助ChatGpt的帮助:NavigationRailView 与 NavHost 组件进行导航,即 每个tab标签对应一组NavHost。以两个tab为例具体步骤:
1.创建多个 NavGraph
在项目中创建多个 NavGraph,每个 NavGraph 代表应用程序的不同区域或不同的功能模块。我们可以使用 navigation 组件在 res 目录下的 navigation 文件夹中创建每个 NavGraph。
2.在 XML 布局文件中添加
NavigationRailView
在主 XML 布局文件中添加 NavigationRailView,并将其与 NavHost 组件进行关联。以下是一个示例 XML 布局文件:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.navigation.NavigationRailView
android:id="@+id/navigation_rail"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:background="#fff"
app:menu="@menu/navigation"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="1.0"
app:itemIconPadding="12dp"
app:itemTextAppearance="@style/TextAppearance.AppCompat.Body2"
app:itemTextColor="@drawable/nav_item_color_state"
app:selectedItem="@id/home" />
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/home_nav"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/navigation_rail"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
3.创建 menu 资源文件
我们需要在 res/menu 目录下创建一个 menu 资源文件,并将其与 NavigationRailView 中的 app:menu 属性关联。在该文件中,我们可以添加菜单项,这些菜单项将用于切换 NavHost 中的不同 NavGraph。以下是一个示例 menu 文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/home"
android:icon="@drawable/ic_home"
android:title="Home" />
<item
android:id="@+id/settings"
android:icon="@drawable/ic_settings"
android:title="Settings" />
</group>
</menu>
此菜单将在 NavigationRailView 中显示两个菜单项,分别用于切换到 home_nav 和 settings_nav。
4.在 Activity 或 Fragment 中实现
NavigationRailView.OnItemSelectedListener
我们需要在 Activity 或 Fragment 中实现 NavigationRailView.OnItemSelectedListener 接口。用户单击 NavigationRailView 中的菜单项时调用。在 onNavigationItemSelected 方法中,我们需要根据用户单击的菜单项 ID 加载相应的 NavGraph。核心代码:
..........
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val navController = nav_host_fragment.findNavController()
when (item.itemId) {
R.id.home -> {
navController.setGraph(R.navigation.home_nav)
return true
}
R.id.settings -> {
navController.setGraph(R.navigation.settings_nav)
return true
}
else -> return false
}
}
}
.......
在 onNavigationItemSelected 方法中,我们获取当前 NavHost 中的 NavController 对象,并根据用户单击的菜单项 ID 加载相应的 NavGraph。每一次切换相当于重新设置新的路由,这样不管在那个标签下进行跳转,再切换标签,之前的fragment都会出栈。保证每一次切换都回到当前标签下的首页。