Situation:
- Fragment A navigates to DialogFragment B (on button click)
- On a given condition in the PositiveButton of B -> navigate to DialogFragment C
Problem:
When clicking the confirmation button of DialogFragment B, then B receives an onDestroy call for this DialogFragment. This is intended anyways and no problem when B does not need to navigate to C.
But: When B navigates to C as requested, the following happens:
- C pops up for a fraction of a second, then disappears
- AND the current position of the navigation controller is not A. I need one backpress to get to A again
I also do not expect the navigation controller to be at A. I want it to be at C displaying the DialogFragment.
Implementation:
Fragment implementations
class FragmentA : Fragment() {
...
// is assigned as onClick listener to the button
fun onClickButton() {
if (findNavController().currentDestination?.id == R.id.FragmentANavId) {
val action = FragmentADirections.actionFragmentAToDialogFragmentB()
findNavController().navigate(action)
}
}
// in separate file
class DialogFragmentB : DialogFragment() {
...
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = MaterialAlertDialogBuilder(requireContext())
...
.setPositiveButton("Save", { _, _ ->
if (...) {
val action = DialogFragmentBDirections.actionDialogFragmentBToDialogFragmentC
findNavController().navigate(action)
}
return builder.create()
}
}
class DialogFragmentC : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = MaterialAlertDialogBuilder(requireContext()) // also tried with requireActivity() as context
...
.setPositiveButton("Confirm", { _, _ ->
// code to handle the user confirmation
}
return builder.create()
}
}
nav_graph.xml
<fragment
android:label="@string/some_text"
android:name="...FragmentA"
android:id="@+id/fragmentA" >
<action
android:id="@+id/action_fragmentA_to_fragmentDialogB"
app:destination="@id/fragmentDialogB" />
</fragment>
// I put them into a nested graph
<navigation android:id="@+id/dialogFragmentsNested"
app:startDestination="@id/fragmentDialogB">
<dialog
android:id="@+id/fragmentDialogB"
android:name="...FragmentDialogB">
<action
android:id="@+id/action_fragmentDialogB_to_fragmentDialogC"
app:destination="@id/fragmentDialogC" />
</dialog>
<dialog
android:id="@+id/fragmentDialogC"
android:name="fragmentDialogC">
</dialog>
</navigation>
Attempts for solution:
- group the dialogFragments as nested graph -> only structural element, does not affect dialog lifecycle
- update the navigation dependencies
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0' // from 2.2.2 implementation 'androidx.navigation:navigation-ui-ktx:2.3.0' // from 2.2.2
- change the context of the dialog in dialogFragmentC to requireActivity()
- try to find related problems
- someone tried to navigate from DialogFragment to Fragment. He wanted the Dialog to remain in the backstack. I want it to be closed, but I want the following dialog to remain open till user interaction
- how to properly close a dialogFragment but I do not want to
navigateUp
- someone complaining that dialogFragment closes when navigating to other fragment. A commenter mentioned: closing a dialog when moving to the next dialog is wanted behaviour. I aggree with that, that is exactly what I want
Summary
When I navigate from DialogFragmentB to DialogFragmentC, then both DialogFragments receive an onDestroy call (as observed by leak-canary).
Am I missing something here? Do you have any suggestions?
How can I move from DialogFragmentB to DialogFragmentC without closing DialogFragmentC immediately (and without user interaction)?