首页 > 解决方案 > 如何将 android 导航 backstack 弹出到某个片段?

问题描述

我再次请求您的智力支持。

我有一个片段,它把自己的许多副本放在导航 backstack 上,如下所示:

Navigation.findNavController(button).navigate(
    TaskCollectFragmentDirections.actionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
)

上面的代码按预期工作。

当我想从导航堆栈中弹出指定数量的这些片段时,问题就来了。(由按下按钮触发。)

我试过这样做:

Navigation.findNavController(button).popBackStack(lastRecurringFragmentId, false)

我的代码编译并运行,但什么也不做。当我没有为popBackStack函数提供参数时,它会正确弹出最上面的片段。我还可以使用后退箭头一直导航到起始片段。

如果它很重要,则lastRecurringFragmentId来自此函数:

fun getLastRecurringFragmentId(recurringFragmentCount: Int): Int {
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment)!!
    val backStackEntryCount = navHostFragment.childFragmentManager.backStackEntryCount
    val indexOfRequested = backStackEntryCount - recurringFragmentCount
    val requestedEntry = navHostFragment.childFragmentManager.getBackStackEntryAt(indexOfRequested)
    return requestedEntry.id
}

导航图如下。应该有几个TaskCollectFragments,最后一个TaskEndFragment在 backstack 的顶部。TaskCollectFragment当用户按下按钮时,我想将一些 s 从堆栈中弹出TaskEndFragment

<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/mobile_navigation"
    app:startDestination="@id/nav_home">

    <fragment
        android:id="@+id/nav_home"
        android:name="ui.home.HomeFragment"
        android:label="@string/menu_home"
        tools:layout="@layout/fragment_home" >
        <action
            android:id="@+id/action_nav_home_to_taskCollectFragment"
            app:destination="@id/taskCollectFragment" />
    </fragment>

    <fragment
        android:id="@+id/taskCollectFragment"
        android:label="TaskCollectFragment"
        tools:layout="@layout/task_collect_fragment"
        >
        <action
            android:id="@+id/action_taskCollectFragment_to_taskEndFragment"
            app:destination="@id/taskEndFragment" />
        <action
            android:id="@+id/action_taskCollectFragment_self"
            app:destination="@id/taskCollectFragment" />
        <argument
            android:name="taskIndex"
            app:argType="integer" />
        <argument
            android:name="screenIndex"
            app:argType="integer" />
    </fragment>
    <fragment
        android:id="@+id/taskEndFragment"
        android:name="ui.task.TaskEndFragment"
        android:label="TaskEndFragment"
        tools:layout="@layout/task_end_fragment">
        <argument
            android:name="taskIndex"
            app:argType="integer" />
    </fragment>
</navigation>

有没有办法可以在满足特定条件之前从后台弹出碎片?

标签: androidkotlinnavigationfragment-backstack

解决方案


我创建了两个几乎相同的片段,forSessionTaskCollectFragmentrecurringTaskCollectFragment使用相同的 viewModel。它们看起来是一样的,从用户的角度来看它们也是一样的。forSessionTaskCollectFragments 是我想要保留的,srecurringTaskCollectFragment是我想稍后弹出的。

从主页片段,我的导航图转到forSessionTaskCollectFragment,从那里循环回到自身或转到recurringTaskCollectFragment也循环回到自身或最后转到TaskEndFragment

<fragment
    android:id="@+id/nav_home"
    android:name="ui.home.HomeFragment"
    android:label="@string/menu_home"
    tools:layout="@layout/fragment_home" >
    <action
        android:id="@+id/action_nav_home_to_orSessionTaskCollectFragment"
        app:destination="@id/forSessionTaskCollectFragment" />
</fragment>

<fragment
    android:id="@+id/forSessionTaskCollectFragment"
    android:name="ui.task.ForSessionTaskCollectFragment"
    android:label="ForSessionTaskCollectFragment" >
    <action
        android:id="@+id/action_forSessionTaskCollectFragment_self"
        app:destination="@id/forSessionTaskCollectFragment" />
    <action
        android:id="@+id/action_forSessionTaskCollectFragment_to_recurringTaskCollectFragment"
        app:destination="@id/recurringTaskCollectFragment" />
    <argument
        android:name="taskIndex"
        app:argType="integer" />
    <argument
        android:name="screenIndex"
        app:argType="integer" />
</fragment>

<fragment
    android:id="@+id/recurringTaskCollectFragment"
    android:name="ui.task.RecurringTaskCollectFragment"
    android:label="TaskCollectFragment"
    tools:layout="@layout/recurring_task_collect_fragment"
    >
    <action
        android:id="@+id/action_recurringTaskCollectFragment_to_taskEndFragment"
        app:destination="@id/taskEndFragment" />
    <action
        android:id="@+id/action_recurringTaskCollectFragment_self"
        app:destination="@id/recurringTaskCollectFragment" />
    <argument
        android:name="taskIndex"
        app:argType="integer" />
    <argument
        android:name="screenIndex"
        app:argType="integer" />
</fragment>

我把forSessionTaskCollectFragments 放在堆栈上,直到我到达我想要返回的点。

Navigation.findNavController(button).navigate(
    if(args.screenIndex < viewModel.forSessionScreenCount) {
        ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
    } else {
        ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentToRecurringTaskCollectFragment(args.taskIndex, args.screenIndex + 1)
    }
)

之后我把我以后要弹回来的片段放回去,最后到TaskEndFragment我要弹我需要的片段的地方:

Navigation.findNavController(button).navigate(
    if(args.screenIndex < viewModel.screenCount - 2) {
        RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
    } else {
        RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentToTaskEndFragment(args.taskIndex)
    }
)

因此,在TaskEndFragment's buttonpress 上,我可以弹回后台堆栈上我标记为从“会话”片段更改为“重复”片段的确切位置:

Navigation.findNavController(button).popBackStack(R.id.forSessionTaskCollectFragment, false)

这很麻烦,我没有找到任何我想做的事情的例子,但最终设法想出了一个可行的解决方案。Ianhanniballake 再次感谢,你激发了我的想法。


推荐阅读