How to correctly dismiss a DialogFragment?
Asked Answered
B

13

140

The docs say this for the dismiss() method from the Dialog class:

Dismiss this dialog, removing it from the screen. This method can be invoked safely from any thread. Note that you should not override this method to do cleanup when the dialog is dismissed, instead implement that in onStop().

In my code, all I do is call getDialog().dismiss() to dismiss it. But I am not doing anything else or even using onStop(). So I am asking exactly how to correctly dismiss a DialogFragment to avoid any memory leaks, etc..

Bonis answered 26/6, 2012 at 5:5 Comment(0)
S
220

tl;dr: The correct way to close a DialogFragment is to use dismiss() directly on the DialogFragment.


Details: The documentation of DialogFragment states

Control of the dialog (deciding when to show, hide, dismiss it) should be done through the API here, not with direct calls on the dialog.

Thus, you should not use getDialog().dismiss(), since that would invoke dismiss() on the dialog. Instead, you should use the dismiss() method of the DialogFragment itself:

public void dismiss()

Dismiss the fragment and its dialog. If the fragment was added to the back stack, all back stack state up to and including this entry will be popped. Otherwise, a new transaction will be committed to remove the fragment.

As you can see, this takes care not only of closing the dialog but also of handling the fragment transactions involved in the process.

You only need to use onStop if you explicitly created any resources that require manual cleanup (closing files, closing cursors, etc.). Even then, I would override onStop of the DialogFragment rather than onStop of the underlying Dialog.

Sequestrate answered 28/8, 2012 at 15:35 Comment(7)
@ScootrNova: It shouldn't, you probably have a bug elsewhere. How are you creating the fragment?Sequestrate
protected void showDialogFragment(final DialogFragment fragment) {final FragmentTransaction fTransaction = getSupportFragmentManager().beginTransaction(); fTransaction.addToBackStack(null); fragment.show(fTransaction, "dialog");} Sorry for the nasty one liner! But yeah you could be right, so for the time being I've wrote up another way to close my DialogFragments. The way that I was dismissing them using the dismiss() method was just finding the fragment by tag and then running dismiss() on it if it wasn't null. Oh and yeah, I'm newing the fragment right before passing it to that method.Darwinism
@ScootrNova: Hmm, don't see anything wrong with that -- on the other hand, I've never used the compatibility library, so I can't be sure about that. Maybe it might make sense to create a minimal, self-contained example and start a new question on that.Sequestrate
@CharlesMadere in those days, did you find a solution?Ululate
Sorry @JCarlos, this was years ago, I'm unsure.Darwinism
I see. If you can, please give me some idea about it: #40351542Ululate
Just wondering: What happens, if I can't stop the dialog from being explicitly dismissed? (e.g. cause I'm using a tool, that expects a dialog, handles it and automatically dimisses it at specific events). Can I just call dismiss() on the DialogFragment afterwards and it will clean up the rest for me?Lancaster
A
90

I think a better way to close a DialogFragment is this:

Fragment prev = getSupportFragmentManager().findFragmentByTag("fragment_dialog");
if (prev != null) {
    DialogFragment df = (DialogFragment) prev;
    df.dismiss();
}

This way you dont have to hold a reference to the DialogFragment and can close it from everywhere.

Appendix answered 5/3, 2014 at 1:30 Comment(0)
T
17

Why don't you try using only this code:

dismiss();

If you want to dismiss the Dialog Fragment by its own. You can simply put this code inside the dialog fragment where you want to dismiss the Dialog.

For example:

button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       dismiss();
   }
});

This will close the recent Dialog Fragment that is shown on the screen.

Hope it helps for you.

Terebinthine answered 14/3, 2019 at 9:41 Comment(1)
That is by far the best and simplest answer. kudos.Avoirdupois
U
6

I gave an upvote to Terel's answer. I just wanted to post this for any Kotlin users:

supportFragmentManager.findFragmentByTag(TAG_DIALOG)?.let {
    (it as DialogFragment).dismiss()
}
Undertint answered 8/10, 2018 at 16:56 Comment(1)
Simple code works hard, Thanks for the update buddy!!Kaja
C
6

Kotlin Version of Terel answer

(fragmentManager.findFragmentByTag(TAG) as? DialogFragment)?.dismiss()
Celle answered 26/10, 2018 at 9:4 Comment(0)
R
4

You should dismiss you Dialog in onPause() so override it.

Also before dismissing you can check for null and is showing like below snippet:

@Override
protected void onPause() {
    super.onPause();
    if (dialog != null && dialog.isShowing()) {
        dialog.dismiss();
    }
}
Rennarennane answered 26/6, 2012 at 5:15 Comment(3)
he has written already that he is doing dismiss() and its about DialogFragment.Never
I thinks this works for both Dialog and DialogFragments @PareshMayaniRennarennane
I believe @PareshMayani is correct Venky. The tutorial on DialogFragment by google does not show the onPause() method being used at all. But I think I see what you are doing. Whats the point though if the user isn't calling onPause(). Thats when the system knows the fragment is being called away. What about when, say a user cancels. Whats a better way to close it up in that case?Bonis
X
3
CustomFragment dialog = (CustomDataFragment) getSupportFragmentManager().findFragmentByTag("Fragment_TAG");
if (dialog != null) {
  dialog.dismiss();
}
Xavierxaviera answered 12/5, 2020 at 11:8 Comment(0)
B
3

Adding to the other answers, when having a DialogFragment that is full screen calling dismiss() won't pop the DialogFragment from the fragment backstack. A workaround is to call onBackPressed() on the parent activity.

Something like this:

CustomDialogFragment.kt

closeButton.onClick {
    requireActivity().onBackPressed()
}
Bonanza answered 28/5, 2020 at 18:51 Comment(0)
C
2

There are references to the official docs (DialogFragment Reference) in other answers, but no mention of the example given there:

void showDialog() {
    mStackLevel++;

    // DialogFragment.show() will take care of adding the fragment
    // in a transaction.  We also want to remove any currently showing
    // dialog, so make our own transaction and take care of that here.
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    Fragment prev = getFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        ft.remove(prev);
    }
    ft.addToBackStack(null);

    // Create and show the dialog.
    DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
    newFragment.show(ft, "dialog");
}

This removes any currently shown dialog, creates a new DialogFragment with an argument, and shows it as a new state on the back stack. When the transaction is popped, the current DialogFragment and its Dialog will be destroyed, and the previous one (if any) re-shown. Note that in this case DialogFragment will take care of popping the transaction of the Dialog is dismissed separately from it.

For my needs I changed it to:

FragmentManager manager = getSupportFragmentManager();
Fragment prev = manager.findFragmentByTag(TAG);
if (prev != null) {
    manager.beginTransaction().remove(prev).commit();
}

MyDialogFragment fragment = new MyDialogFragment();
fragment.show(manager, TAG);
Campanile answered 4/5, 2019 at 9:42 Comment(0)
O
1

I found that when my fragment was defined in the navigation graph with a <fragment> tag (for a full screen dialogfragment), the dialogfragment would not dismiss with the dismiss() command. Instead, I had to pop the back stack:

findNavController(getActivity(), R.id.nav_host_fragment).popBackStack();

However, if the same dialogfragment was defined in the navigation graph with a <dialog> tag, dismiss() works fine.

Otology answered 27/4, 2020 at 13:4 Comment(0)
P
1

Here is a simple AppCompatActivity extension function, which closes opened Dialog Fragment:

fun AppCompatActivity.whenDialogOpenDismiss(
    tag: String
) {
    supportFragmentManager.findFragmentByTag(tag)?.let { 
        if(it is DialogFragment) it.dismiss() }
}

Of course you can call it from any activity directly. If you need to call it from a Fragment just make the same extension function about Fragment class

Posit answered 14/1, 2021 at 18:14 Comment(0)
D
0

Just call dismiss() from the fragment you want to dismiss.

imageView3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dismiss();
        }
    });
Dupion answered 26/4, 2019 at 8:2 Comment(0)
C
0

Consider the below sample code snippet which demonstrates how to dismiss a dialog fragment safely:

DialogFragment dialogFragment = new DialogFragment();

/** 
 * do something
 */

// Now you want to dismiss the dialog fragment
if (dialogFragment.getDialog() != null && dialogFragment.getDialog().isShowing())
{
    // Dismiss the dialog
    dialogFragment.dismiss();
}

Happy Coding!

Causeuse answered 16/12, 2020 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.