Preventing the back button from cancelling a DialogFragment
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;
}
MattF
Updated on July 09, 2022Comments
-
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 about 12 yearsThis is correct! it turns out you have to call setCancelable(false) on the DialogFragment itself, not the inner Dialog that it holds!
-
MattF about 12 yearsI ended up going with the other answer but I do think this works as well, many thanks
-
Daniel about 10 yearsThis does not work. You have to call
setCancelable(boolean)
on theDialogFragment
, not on theDialog
which is what you are doing now. -
Fattie almost 10 yearsGREAT tip. And here's an important further point on that stackoverflow.com/a/16480564/294884
-
prolink007 over 8 years@MattF This comment is a life saver. Did not realize i needed to call
setCancelable()
on theDialogFragment
instead of theProgressDialog
. Thanks! -
Seven about 5 yearsI used
isCancelable = false
in Kotlin, inside ofonViewCreated
and it worked!! -
Fernando Perez almost 5 yearsIt works for me too @Seven, i use isCancelable = false (not dialog.setCancelable(false))
-
Ehsan over 4 yearsI was using
getDialog.setCancelable(false)
and it didn't work, but I replaced it withsetCancelable(false)
and it works correctly. that's was weird -
Ashraf Amin almost 3 yearsFor custom DialogFragment add isCancelable = false at onCreateDialog