Preventing the back button from cancelling a DialogFragment

26,467

Solution 1

How about using setCancelable? Did you try it?

From the Docs:

Control whether the shown Dialog is cancelable. Use this instead of directly calling Dialog.setCancelable(boolean), because DialogFragment needs to change its behavior based on this

For custom DialogFragment

Add isCancelable = false at onCreateDialog

Solution 2

 DialogFragment newFragment = YourFragment.newInstance();
                newFragment.setCancelable(false);
                newFragment.show(fragmentTransaction, "dialog");

Add setCancelable(false) before you .Show() the fragment

Solution 3

I'm not at all sure if this'll work with FragmentDialogs, but if the setCancelable didn't work for you, it might be worth having a look at this article: Android: Prompt user to save changes when Back button is pressed

It explains how to detect the back button being pressed. So maybe you can suppress the button press and it'll stop the dialog from closing?

Solution 4

onCreateDialog vs onCreateView:

Implementations should override this class and implement onCreateView(LayoutInflater, ViewGroup, Bundle) to supply the content of the dialog. Alternatively, they can override onCreateDialog(Bundle) to create an entirely custom dialog, such as an AlertDialog, with its own content.

Important when using onCreateDialog:

Override to build your own custom Dialog container. This is typically used to show an AlertDialog instead of a generic Dialog; when doing so, onCreateView(LayoutInflater, ViewGroup, Bundle) does not need to be implemented since the AlertDialog takes care of its own content.

Example Dialog (In this case an AlertDialog):

public static class MyAlertDialogFragment extends DialogFragment {

    public static MyAlertDialogFragment newInstance(int title) {
        MyAlertDialogFragment frag = new MyAlertDialogFragment();
        Bundle args = new Bundle();
        args.putInt("title", title);
        frag.setArguments(args);
        return frag;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        int title = getArguments().getInt("title");

        return new AlertDialog.Builder(getActivity())
                .setIcon(R.drawable.alert_dialog_icon)
                .setTitle(title)
                .setCanceble(false)
                .setPositiveButton(R.string.alert_dialog_ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            ((FragmentAlertDialog)getActivity()).doPositiveClick();
                        }
                    }
                )
                .setNegativeButton(R.string.alert_dialog_cancel,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            ((FragmentAlertDialog)getActivity()).doNegativeClick();
                        }
                    }
                )
                .create();
    }
} 

The property setCanceble(boolean) states whether you can exit the Dialog with a back press. No need to catch the KEYCODE_BACK anywhere.

Solution 5

It may help you.

newFragment.setCancelable(false); 

make changes like above when creating DialogFragment object or in the constructor of Custom DialogFragment as in the sample below.

public static CustomClearHourDialog newInstance(Bundle args, IDialogListener listener)
        {
            CustomClearHourDialog clearHourDialog = new CustomClearHourDialog();            
            CustomClearHourDialog.listener = listener;
            clearHourDialog.setCancelable(false);
            return clearHourDialog;
        }
Share:
26,467
MattF
Author by

MattF

Updated on July 09, 2022

Comments

  • MattF
    MattF almost 2 years

    I have a Fragment that can create and pop up a DialogFragment, but when I hit the back button, it dismisses the dialog even though I explicitly call setCancelable(false); Is there any way for my DialogFragment to be insensative to the back button?

    public class LoadingDialogFragment extends DialogFragment
    {
        String title;
        String msg;
    
        public LoadingDialogFragment()
        {
            this.title = "Loading...";
            this.msg = "Please wait...";
        }
        public LoadingDialogFragment(String title, String msg)
        {
            this.title = title;
            this.msg = msg;
        }
    
        @Override
        public Dialog onCreateDialog(final Bundle savedInstanceState)
        {
            final ProgressDialog dialog = new ProgressDialog(getActivity());
    
            dialog.setTitle(title);
            dialog.setMessage(msg);
            dialog.setIndeterminate(true);
            dialog.setCanceledOnTouchOutside(false);
            dialog.setCancelable(false);
    
            return dialog;
        }
    
    }
    

    I create the DialogFragment from an AsyncTask:

    private class GpsTask extends AsyncTask<String, Integer, Integer>
    {
        //ProgressDialog dialog;
        @Override
        protected void onPreExecute()
        {
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            DialogFragment newFragment = new LoadingDialogFragment("Gathering Location", "Acquiring GPS lock...");
            ft.addToBackStack(null);
            newFragment.show(ft, "dialog");
        }
    
        @Override
        protected Integer doInBackground(String... params)
        {
            //acquire a GPS lock and grab a few position updates
        }
    
        @Override
        protected void onProgressUpdate(Integer... input) { }
    
        @Override
        protected void onPostExecute(Integer result)
        {
            getSupportFragmentManager().popBackStackImmediate();
        }
    }
    
  • MattF
    MattF about 12 years
    This is correct! it turns out you have to call setCancelable(false) on the DialogFragment itself, not the inner Dialog that it holds!
  • MattF
    MattF about 12 years
    I ended up going with the other answer but I do think this works as well, many thanks
  • Daniel
    Daniel about 10 years
    This does not work. You have to call setCancelable(boolean) on the DialogFragment, not on the Dialog which is what you are doing now.
  • Fattie
    Fattie almost 10 years
    GREAT tip. And here's an important further point on that stackoverflow.com/a/16480564/294884
  • prolink007
    prolink007 over 8 years
    @MattF This comment is a life saver. Did not realize i needed to call setCancelable() on the DialogFragment instead of the ProgressDialog. Thanks!
  • Seven
    Seven about 5 years
    I used isCancelable = false in Kotlin, inside of onViewCreated and it worked!!
  • Fernando Perez
    Fernando Perez almost 5 years
    It works for me too @Seven, i use isCancelable = false (not dialog.setCancelable(false))
  • Ehsan
    Ehsan over 4 years
    I was using getDialog.setCancelable(false) and it didn't work, but I replaced it with setCancelable(false) and it works correctly. that's was weird
  • Ashraf Amin
    Ashraf Amin almost 3 years
    For custom DialogFragment add isCancelable = false at onCreateDialog