79

I launch my dialog fragment using

FragmentTransaction ft = 
getFragmentManager().beginTransaction();
MyDialogFragment dialog = new MyDialogFragment()
dialog.show(ft, "dialog");

then to get a handle on it I do

Fragment prev = getFragmentManager().findFragmentByTag("dialog");

but once I get prev, how do I check if it is showing?

Back Story

My problem is that my looping code keeps launching the dialog again and again. But if the dialog is already showing, I don't want it to launch again. This back story is just for context. The answer I seek is not: "move it out of the loop."

learner
  • 11,490
  • 26
  • 97
  • 169

5 Answers5

152
 if (dialogFragment != null
     && dialogFragment.getDialog() != null
     && dialogFragment.getDialog().isShowing()
     && !dialogFragment.isRemoving()) {
            //dialog is showing so do something 
 } else {
     //dialog is not showing
 }

UPDATE: team can you also try the below call, i think it will work logically:

dialogFragment.isResumed

that should mean its in the foreground displaying if im not mistaken.

j2emanue
  • 60,549
  • 65
  • 286
  • 456
57

I added this to be inside my custom dialog fragment, so I don't have to worry about any logic on the outside. Override the show() and onDismiss() methods, with a boolean shown field:

  private static boolean shown = false;

    @Override
    public void show(FragmentManager manager, String tag) {
        if (shown) return;

        super.show(manager, tag);
        shown = true;
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        shown = false;
        super.onDismiss(dialog);
    }

If you want to check whether it is shown or not, you can create a getter for the shown boolean.

Arpit Patel
  • 7,212
  • 5
  • 56
  • 67
John Leehey
  • 22,052
  • 8
  • 61
  • 88
  • 18
    Not the best answer, If user receive call while dialog is showing the dialog will added twice because variable `show` will created again with value `false`, You must to make `show` variable `static`, `private static boolean shown = false;` – Ibrahim Disouki Apr 21 '15 at 13:47
  • 1
    +1 for the previous comment and also: this approach is not applicable if you create a new instance from the outside for each dialog invocation. One could argue that you could make "shown" static but I think this would have other implications – avalancha Oct 02 '15 at 12:21
  • 1
    See https://stackoverflow.com/a/51934699/2914140: in `void show(…)` change line: `if (shown || manager.isStateSaved()) return;`. – CoolMind Aug 20 '18 at 16:14
  • You're also going to want to override onCancel and set shown = false there or dismissing by tapping outside of dialog won't call onDismiss and "shown" will remain stuck on true. I tried to edit the answer but the edit queue is full. – Flyview Dec 06 '22 at 01:00
35

simply check if it's null

if(prev == null)
    //There is no active fragment with tag "dialog"
else
    //There is an active fragment with tag "dialog" and "prev" variable holds a reference to it.

Alternatively, you could check the activity the fragment prev is currently associated with, however, make sure you ask that after you make sure it's not null or you'll get a NullPointerException. Like this:

if(prev == null)
    //There is no active fragment with tag "dialog"
else
    if(prev.getActivity() != this) //additional check
        //There is a fragment with tag "dialog", but it is not active (shown) which means it was found on device's back stack.
    else
        //There is an active fragment with tag "dialog"
nstosic
  • 2,584
  • 1
  • 17
  • 21
  • 4
    This doesn't always work, for example if the dialog has just been dismissed. I ran into this problem when I sometimes wanted to show a dialog immediately after it was dismissed (I reused the same fragment to show a "different" dialog). The solution I found to be working is the same as by @j2emanue below. `if (fragment.getDialog() == null || !fragment.getDialog().isShowing()) { fragment.show(fragmentManager, tag); }` (in my case I already know that my fragment is not null). – LoPoBo Nov 22 '16 at 09:25
3

100% Uptime

class ProgressDialogFragment : DialogFragment() {

 companion object {
    private val TAG = this::class.simpleName
 }

 lateinit var dialogFragmentManager: FragmentManager
 
 fun showDialog() {
    dialogFragmentManager.apply {
       if (findFragmentByTag(TAG) == null) show(this, TAG) else return
    }
 }

}

lateinit var progressDialog: ProgressDialogFragment

Init:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
   
    initProgressDialog(supportFragmentManager)
}

fun initProgressDialog(fragmentManager: FragmentManager){
    progressDialog = ProgressDialogFragment().apply {
        dialogFragmentManager = fragmentManager
    }
}

Use { progressDialog.showDialog() } everywhere

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 1
    This is gonna be disappointing to you "great" finding but just call `progressDialog.showDialog()` twice back-to-back and you will get two dialogs. Because `show` is asynchronous and your `findFragmentByTag(TAG) == null` check will be true until dialog is actually added by system. – Farid Dec 21 '21 at 05:25
-1

Kotlin style:

private fun showDialog(dialogFragment: DialogFragment, tag: String) {
    supportFragmentManager.findFragmentByTag(tag).let { fragment ->
        fragment ?: let {
            supportFragmentManager.beginTransaction().let { transition ->
                dialogFragment.show(transition, tag)
            }
        }
    }
}
drindt
  • 901
  • 10
  • 15
  • Sorry, this problem is not even solved technically so there is no need to jam in your Kotlin "solution" – Farid Dec 21 '21 at 05:28