I need to find out from which fragment the user switched to another fragment. I thought I should use the fragment name, but how do I get that name? Or is my method not very reliable and there are some other options?
P.S.: I use NavHostFragment
and Kotlin
Instead of the headache of tracking the previous fragment with passed-in arguments, you'd use previousBackStackEntry which returns a NavBackStackEntry
that is:
the previous visible entry on the back stack or null if the back stack has less than two visible entries
So, to get the id of the previous destination use: previousBackStackEntry?.destination?.id
For instance, assume you've 3 fragments: fragment_a, fragment_b, and fragment_c. And at the fragment_c you need to know from which it's reached:
To know the previous fragment in fragment_c:
val previousFragment = findNavController().previousBackStackEntry?.destination?.id
previousFragment?.let {
when (previousFragment) {
R.id.fragment_a_id ->
// The previous fragment is Fragment a
R.id.fragment_b_id ->
// The previous fragment is Fragment b
else ->
// The previous fragment is neither Fragment a nor b
}
}
You'd consider passing some data between destinations/fragments; for instant you would consider the passed-in data to be integers; and create constant integers for each fragment, whenever you do a navigation, then pass the constant assigned for the current fragment.
By using safe Args for actions & passing data during the navigation.
Assuming we want to navigate from FragmentA
to FragmentB
:
The NavGraph
should have an action represents the direction and an argument to be set to the origin fragment during the 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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/fragmentA"
android:name="......FragmentA"
android:label="....">
<action
android:id="@+id/action_fragment_a_to_fragment_b"
app:destination="@id/fragmentB" />
<argument
android:name="previousFragment"
android:defaultValue="-1"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="......FragmentB"
android:label="....">
<argument
android:name="previousFragment"
android:defaultValue="-1"
app:argType="integer" />
</fragment>
</navigation>
Create the constants that correspond to destination fragments:
companion object {
const val FRAGMENT_A = 101
const val FRAGMENT_B = 102
}
And the navigation action from FragmentA to FragmentB:
Do the navigation @FragmentA
:
findNavController().navigate(
FragmentADirections.actionFragmentAToFragmentB()
.setPreviousFragment(FRAGMENT_A)
Then check that @FragmentB
:
val args: FragmentBArgs = FragmentBArgs.fromBundle(requireArguments())
when (val previousFragment = args.previousFragment) {
FRAGMENT_A -> {
Log.d("LOG_TAG", "$previousFragment") // Should print 101
}
// Complete the rest of fragment cases
}