动态更改 BottomNavigationView 内嵌套导航图的 startDestination

Dynamically change startDestination of nested navigation graph inside of a BottomNavigationView

我正在尝试更新我的应用程序以使用 BottomNavigationView。第一个选项卡包含一个 HostFragment 和一个加载微调器,该微调器执行网络请求以确定哪个片段(HomeFragmentLockedFragment 应显示在该选项卡中。

MainActivity 处理 BottomNavigationView:

的初始设置
class MainActivity : AppCompatActivity() {

    private lateinit var navController: NavController
    private lateinit var appBarConfiguration: AppBarConfiguration

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHostFragment = supportFragmentManager.findFragmentById(
            R.id.nav_host_container
        ) as NavHostFragment
        navController = navHostFragment.navController

        val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
        bottomNavigationView.setupWithNavController(navController)

        appBarConfiguration = AppBarConfiguration(
            setOf(R.id.mainFragment)
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
    }

我的主导航图如下所示:

<?xml version="1.0" encoding="utf-8"?>
<navigation
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@+id/home">

    <include app:graph="@navigation/home"/>
    <include app:graph="@navigation/list"/>
    <include app:graph="@navigation/form"/>
</navigation>

主图如下所示:

<?xml version="1.0" encoding="utf-8"?>
<navigation
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/home"
    app:startDestination="@+id/hostFragment">

    <fragment
        android:id="@+id/hostFragment"
        android:name="com.example.android.bottomnav.homescreen.HostFragment"
        android:label="Host">
        <action
            android:id="@+id/action_hostFragment_to_homeFragment"
            app:destination="@id/homeFragment" />
        <action
            android:id="@+id/action_hostFragment_to_lockedFragment"
            app:destination="@id/lockedFragment" />
    </fragment>

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.android.bottomnav.homescreen.HomeFragment"
        android:label="Home" />

    <fragment
        android:id="@+id/lockedFragment"
        android:name="com.example.android.bottomnav.homescreen.LockedFragment"
        android:label="Locked"/>
</navigation>

HostFragment 显示正常并加载数据:

class HostFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_host, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        determineFragmentToShow()
    }

    private fun determineFragmentToShow() {
        lifecycleScope.launchWhenStarted {
            // mock network call to determine tab
            delay(1500)

            // show HomeFragment for the sake of the example, but note that
            // this would be dependent on the network call's result above
            findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
        }
    }
}

成功导航到 HomeFragment

现在的问题是,每当我从 HomeFragment 按下后退按钮时,它都会返回 HostFragment 而不是关闭应用程序。You can see the behavior in this video here.

我尝试在 home.xml 中设置 popUpTopopUpInclusive 标签,如下所示:

    <fragment
        android:id="@+id/hostFragment"
        android:name="com.example.android.bottomnav.homescreen.HostFragment"
        android:label="Host">
        <action
            android:id="@+id/action_hostFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:popUpTo="@id/home"
            app:popUpToInclusive="true"/>
        <action
            android:id="@+id/action_hostFragment_to_lockedFragment"
            app:destination="@id/lockedFragment"
            app:popUpTo="@id/home"
            app:popUpToInclusive="true"/>
    </fragment>

当从 HomeFragment 返回时,应用程序会关闭,但现在每次我切换到新选项卡时,它都会创建一个新的片段实例并将其添加到后台堆栈。然后按下后退按钮将向后遍历它们。 You can see that behavior in this video here.

那么如何更新嵌套导航图的起始目的地呢?

我正在使用最新的 2.4.0-alpha10 导航组件,这样我就可以获得对多个后台堆栈的本机支持。非常感谢任何帮助!

我能够利用答案 here 获得适合我的解决方案。

HostFragment 中的 determineFragmentToShow() 内部,我只是将 findNavController().navigate(R.id.action_hostFragment_to_homeFragment) 替换为

val navController = findNavController()
val graph = navController.graph
val walletGraph = graph.findNode(R.id.home) as NavGraph
walletGraph.setStartDestination(R.id.homeFragment)
navController.navigate(R.id.action_hostFragment_to_homeFragment)

我仍然需要在此处包含 popUpTopopUpInclusive 标签

    <fragment
        android:id="@+id/hostFragment"
        android:name="com.example.android.bottomnav.homescreen.HostFragment"
        android:label="Host">
        <action
            android:id="@+id/action_hostFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:popUpTo="@id/home"
            app:popUpToInclusive="true"/>
        <action
            android:id="@+id/action_hostFragment_to_lockedFragment"
            app:destination="@id/lockedFragment"
            app:popUpTo="@id/home"
            app:popUpToInclusive="true"/>
    </fragment>

但这让我得到了我想要的背部行为!