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?
PS: 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
And to get the id of the previous destination use: previousBackStackEntry.destination.id
but as it is nullable then 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
}
you can add OnDestinationChangedListener to your NavController to track the fragment changes.
val navhostContainer = supportFragmentManager.findFragmentById(R.id.nav_host_container)
controller = navhostContainer!!.findNavController()
controller.addOnDestinationChangedListener(listener)
val listener = NavController.OnDestinationChangedListener{
controller, destination, arguments ->
println("Destination Observe: ${destination.label}")
}
When the fragment is changed, listener will be triggered.
I hope that solution helps to solve your issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.