使用导航组件防止 BottomNavigationView 中的循环导航逻辑

Prevent circular navigation logic in BottomNavigationView using Navigation component

我有一个 BottomNavigationView 通过 Navigation 组件连接了最多 3 个片段(A、B 和 C)。我还有一个登录片段,我在成功登录后将其从堆栈中弹出。

观察到的导航行为:

A > B > C > A > B > C > B > 返回 > C > 返回 > B > 返回 > A > 返回 > 退出

预期行为:

(阅读@ianhanniballake 和Principles of navigation 的评论后)

A > B > C > A > B > C > B > 返回 > A > 返回 > 退出

我的问题类似于circular navigation logic,但我在BottomNavigationView中有。如何实现我的预期行为?

main_nav.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_nav"
    app:startDestination="@id/login_fragment">

    <fragment
        android:id="@+id/login_fragment"
        android:name="com.example.app.LoginFragment"
        android:label="Login">

        <action
            android:id="@+id/login_action"
            app:destination="@id/home_fragment"
            app:launchSingleTop="true"
            app:popUpTo="@id/main_nav"
            app:popUpToInclusive="true" />

    </fragment>

    <!-- Fragments A, B and C tied to BottomNavigationView-->

</navigation>

BottomNavigationView设置

navController = findNavController(R.id.main_nav_host)
mainActivityBinding.bottomNavView.setupWithNavController(navController)

在这种情况下,您需要将登录流程设置为主导航图中的嵌套图。

你的起始目的地应该被分配给连接到你的BottomNavigationView的3个片段之一,以便按返回在退出应用程序之前将用户带到此屏幕。

在您的 HomeFragment(开始目的地)中,您可以检查用户是否已登录,并在需要时导航至嵌套登录图。

HomeFragment.kt

if (!isLoggedIn) {
    val action = HomeFragmentDirections.showLogin()
    findNavController().navigate(action)
} else {
    // show bottom nav
}

您必须根据需要处理 hiding/showing BottomNavigationView

您更新后的导航图将如下所示:

main_nav.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_nav"
    app:startDestination="@id/home">

    <fragment
        android:id="@+id/home"
        android:name="com.example.app.HomeFragment"
        android:label="Home">

        <action
            android:id="@+id/show_login"
            app:destination="@id/login_nav"/>

    </fragment>

    <!-- Fragments B and C -->

    <include app:graph="@navigation/login_nav"/>

</navigation>