73

When

  • Touch outside the dialog region
  • Press on back button

I'm expecting onDismiss (Or onCancel) will be called. However, both of them are not called. May I know is there anything I'm missing? From AlertDialog setOnDismissListener not working, I thought onCancel will be called when I press back button. But it doesn't work for me. May I know is there anything I had missed out?

public class RateAppDialogFragment extends SherlockDialogFragment {
    public static RateAppDialogFragment newInstance() {
        RateAppDialogFragment rateAppDialogFragment = new RateAppDialogFragment();
        return rateAppDialogFragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // Get the layout inflater
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.rate_app_dialog_fragment, null);

        Utils.setCustomTypeFace(view, Utils.ROBOTO_LIGHT_TYPE_FACE);

        final AlertDialog dialog = new AlertDialog.Builder(this.getSherlockActivity())            
        .setTitle("Love JStock?")
        .setView(view)
        // Add action buttons
        .setPositiveButton("Rate 5 stars \u2605", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int id) {
                Utils.showShortToast("Rate");
            }
        })
        .setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                Utils.showShortToast("No");
            }
        })
        .setNeutralButton("Later", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                Utils.showShortToast("Later");
            }
        })
        .create();

        dialog.setCanceledOnTouchOutside(true);

        dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                Utils.showShortToast("Back button pressed?");
            }
        });

        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {

            @Override
            public void onDismiss(DialogInterface dialog) {
                // TODO Auto-generated method stub
                Utils.showShortToast("Back button pressed?");
            }
        });

        return dialog;
    }

}

    FragmentManager fm = fragmentActivity.getSupportFragmentManager();
    if (fm.findFragmentByTag(RATE_APP_DIALOG_FRAGMENT) != null) {
        return;
    }

    RateAppDialogFragment rateAppDialogFragment = RateAppDialogFragment.newInstance();
    rateAppDialogFragment.show(fm, RATE_APP_DIALOG_FRAGMENT);  
Community
  • 1
  • 1
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

5 Answers5

171

The problem happens when you are using DialogFragment to display Dialog

According to http://developer.android.com/reference/android/app/DialogFragment.html, the solution is to override onCancel in DialogFragment

Please take note from http://developer.android.com/reference/android/app/DialogFragment.html#onCreateDialog(android.os.Bundle) too

Note: DialogFragment own the Dialog.setOnCancelListener and Dialog.setOnDismissListener callbacks. You must not set them yourself. To find out about these events, override onCancel(DialogInterface) and onDismiss(DialogInterface).

// This is DialogFragment, not Dialog
@Override
public void onCancel(DialogInterface dialog) {
}
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • 1
    nice solution! It is actually the way to work with Cancel in DialogFragment. – sud007 Aug 09 '16 at 10:07
  • 1
    it works if you leave `super.onCancel(dialog)`.. I am able to trigger my action right after, and `cancel` button doesn't end up having this method call which is good – Juan Mendez Jul 31 '19 at 20:00
  • @Cheok Yan Cheng I have a similar use case and set up onCancel() based on your recommendation above. Sometimes it takes multiple clicks outside the dialog (I am using a DatePickerDialog within a DilaogFragment) for the dialog to finally dimiss. Any ideas on how to capture the first touch outside the dialog so that I can dismiss the dialog immediately? – AJW Feb 04 '20 at 05:29
  • I have an AlertDialog inside a DialogFragment. Both onCancel() and onDismiss() are called in DialogFragment when I a) backpress b) press cancel button c) or accept button on the AlertDialog setOnCancelListener() is not allowed apparently on AlertDialog as it crashed at runtime. Am a bit lost here. – tuxdost Oct 26 '22 at 23:06
13

If you are using AlertDialog, see

builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        // dialog dismiss without button press
    }
});

and dialog.setCanceledOnTouchOutside(true) (thanks @LeosLiterak)

Hugo Gresse
  • 17,195
  • 9
  • 77
  • 119
  • and add dialog.setCanceledOnTouchOutside(true) as well – Leos Literak Oct 09 '16 at 11:13
  • 2
    java.lang.IllegalStateException: You can not set Dialog's OnCancelListener or OnDismissListener – Joe Aug 08 '17 at 19:08
  • Do not work either with builder (at least to me), tested on API 21. – ARLabs Mar 22 '18 at 10:24
  • @Joe That's because you're using it with `DialogFragment` (see [this question](https://stackoverflow.com/questions/14520597/illegalstateexception-you-can-not-set-dialogs-oncancellistener-or-ondismissli)). Use AlertDialog, it is working. – Vadim Kotov Dec 04 '19 at 10:49
  • @VadimKotov For me AlertDialog is giving the exception java.lang.RuntimeException: Unable to resume activity {SomeActivity}: java.lang.IllegalStateException: You can not set Dialog's OnCancelListener or OnDismissListener – tuxdost Oct 26 '22 at 21:36
5

You have not set backPressed key event

dialog.setOnKeyListener(new Dialog.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface arg0, int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            finish();
        }
        return true;
    }
});
MysticMagicϡ
  • 28,593
  • 16
  • 73
  • 124
SilentKiller
  • 6,944
  • 6
  • 40
  • 75
  • 1
    But, how about touching outside the dialog box region? Also, you have idea why setOnCancelListener and setOnDismissListener doesn't work? They should work, isn't it? – Cheok Yan Cheng Aug 16 '13 at 08:47
  • As you got the solution. i'll say that was big and silly mistake.. :D its compulsory that if you are overriding the default method you have to right `@override` on it. – SilentKiller Aug 16 '13 at 10:54
3

you should read this topic: How to dismiss the dialog with click on outside of the dialog?

Dialog dialog = new Dialog(context)
dialog.setCanceledOnTouchOutside(true);
Community
  • 1
  • 1
Jack
  • 724
  • 1
  • 8
  • 15
2

in your DialogFragment, override

@Override
public void onStop() {
    super.onStop();
    if (mListener != null) {
       // do something here
    }
}
Son Nguyen Thanh
  • 1,199
  • 15
  • 19