I am once again asking for your intellectual support.
I have a fragment that puts a number of copies of itself on the navigation backstack like this:
Navigation.findNavController(button).navigate(
TaskCollectFragmentDirections.actionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
)
The code above works as intended.
The problem comes, when I want to pop a specified number of these fragments off the navigation backstack. (Triggered by a buttonpress.)
I've tried to do it like this:
Navigation.findNavController(button).popBackStack(lastRecurringFragmentId, false)
My code compiles and runs, but simply does nothing. When I give no parameters to the popBackStack
function, it properly pops off the topmost fragment. I can also use the back arrow to navigate back all the way to the starting fragment.
If it is of any importance, the lastRecurringFragmentId
comes from this function:
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
}
The navigation graph is as follows. There are supposed to be several TaskCollectFragment
s and lastly one TaskEndFragment
on the top of the backstack. I want to pop some of the TaskCollectFragment
s off the stack when the user presses a button on the 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>
Is there a way I can pop fragments off the backstack until a certain condition is met?
I created two almost identical fragments, forSessionTaskCollectFragment
and recurringTaskCollectFragment
with the same viewModel. They look the same and from the user's point of view they do the same.
The forSessionTaskCollectFragment
s are the ones I want to keep and the recurringTaskCollectFragment
s are the ones I want to pop back later.
From the home fragment, my navigation graph goes to the forSessionTaskCollectFragment
, from there it loops back on itself or goes to the recurringTaskCollectFragment
which also loops back to itself or finally goes to the 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>
I put forSessionTaskCollectFragment
s on the stack until I get to the point to which I want to return.
Navigation.findNavController(button).navigate(
if(args.screenIndex < viewModel.forSessionScreenCount) {
ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
} else {
ForSessionTaskCollectFragmentDirections.actionForSessionTaskCollectFragmentToRecurringTaskCollectFragment(args.taskIndex, args.screenIndex + 1)
}
)
After that I put the fragments I later want to pop back, and finally go to the TaskEndFragment
from where I want to pop the fragments I need to:
Navigation.findNavController(button).navigate(
if(args.screenIndex < viewModel.screenCount - 2) {
RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentSelf(args.taskIndex, args.screenIndex + 1)
} else {
RecurringTaskCollectFragmentDirections.actionRecurringTaskCollectFragmentToTaskEndFragment(args.taskIndex)
}
)
So on the TaskEndFragment
's buttonpress I can pop back to the exact place on the backstack that I marked with changing from "session" fragments to "recurring" fragments:
Navigation.findNavController(button).popBackStack(R.id.forSessionTaskCollectFragment, false)
This was a lot of hassle, I did not find any example for the thing I wanted to do, but finally managed to come up with a working solution. Ianhanniballake thanks again, you triggered my idea.