NavigationRailView + fragment + Navigation

有一种场景,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都会出栈。保证每一次切换都回到当前标签下的首页。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容