I have an Activity layout that surrounds the fragment container in a CoordinatorLayout. When switching destinations, I want to hide the FAB and dismiss the SnackBar if either is currently displayed, and let the destination Fragment reshow the FAB if it needs to in its onViewCreated()
. This is consistent with the Material Design guidelines that say the FAB should visibly disappear and reappear when you switch destinations.
So I did this:
navController.addOnDestinationChangedListener { _, navDestination, _ ->
binding.floatingActionButton.apply {
hide()
setOnClickListener(null)
}
currentSnackbar?.dismiss()
//...
}
However, when a DialogFragment is the navigation destination, the previous Fragment will not have onViewCreated()
called again when navigating back, because it never left the screen.
NavDestination doesn't seem to have any way to inspect whether it represents a DialogFragment, even though the XML distinguishes between fragment
and dialog
.
I realize I could move the FAB showing code to onResume
in the fragment, but it would look silly to hide it in the first place when only opening an alert dialog. I realize I could also create a parent Fragment class that hides it in onStop()
, but I try to avoid creating class hierarchy layers when possible to make code less fragile (composition over inheritance), and I also want to avoid repeating the code all over the app.
Dialog destinations implement the FloatingWindow
interface:
A marker interface for
NavDestination
subclasses that float above the view of other destinations (i.e.DialogFragmentNavigator.Destination
).
NavController.OnDestinationChangedListener
instances can also customize their behavior based on whether the destination is aFloatingWindow
.
Therefore you can ignore navigating to dialog by using if (!(navDestination is FloatingWindow))
.