防止后退按钮取消DialogFragment

56

我有一个Fragment可以创建并弹出DialogFragment,但当我按下返回按钮时,它会关闭对话框,即使我明确地调用了setCancelable(false)。 有没有办法让我的DialogFragment对返回按钮不敏感?

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;
    }

}

我从AsyncTask创建DialogFragment:

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();
    }
}
5个回答

141
我建议使用setCancelable,你试过了吗?
来自文档:
控制显示的对话框是否可取消。请使用此方法而不是直接调用Dialog.setCancelable(boolean),因为DialogFragment需要根据此更改其行为。
对于自定义的DialogFragment,请在onCreateDialog中添加isCancelable = false

42
没问题!原来需要调用setCancelable(false)的对象是DialogFragment本身,而不是内部包含的Dialog! - MattF
2
@MattF 这个评论真是救了我一命。我没有意识到需要在 DialogFragment 上调用 setCancelable() 而不是 ProgressDialog。谢谢! - prolink007
3
我在 Kotlin 中使用了 isCancelable = false,放在 onViewCreated 里面,它起作用了! - Seven
对我也有效,@Seven,我使用的是isCancelable = false(而不是dialog.setCancelable(false))。 - Fernando Perez
我曾经使用 getDialog.setCancelable(false),但它没有起作用,但是我将其替换为 setCancelable(false),现在它可以正常工作了。这很奇怪。 - Ehsan
对于自定义的 DialogFragment,在 onCreateDialog 中添加 isCancelable = false。 - Ashraf Amin

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

在展示碎片之前,添加setCancelable(false)。

很好的提示。并且这里还有一个重要的进一步说明 https://dev59.com/G2Qn5IYBdhLWcg3w5qlg#16480564 - Fattie

4
我不确定这是否适用于FragmentDialogs,但是如果setCancelable对您无效,则可能值得查看此文章:Android:用户按下返回按钮时提示保存更改
它解释了如何检测返回按钮被按下。因此,也许您可以抑制按钮按下,这样就可以防止对话框关闭?

我最终选择了另一个答案,但我认为这个也可以,非常感谢。 - MattF

3
这可能会对你有帮助。
newFragment.setCancelable(false); 

在创建DialogFragment对象时,或者像下面示例中的Custom DialogFragment构造函数中一样进行更改。
public static CustomClearHourDialog newInstance(Bundle args, IDialogListener listener)
        {
            CustomClearHourDialog clearHourDialog = new CustomClearHourDialog();            
            CustomClearHourDialog.listener = listener;
            clearHourDialog.setCancelable(false);
            return clearHourDialog;
        }

3

onCreateDialogonCreateView的区别:

应该重写此类并实现onCreateView(LayoutInflater, ViewGroup, Bundle)以提供对话框的内容。或者,他们可以重写onCreateDialog(Bundle)来创建一个完全自定义的对话框,例如AlertDialog,具有自己的内容。

使用onCreateDialog时很重要:

重写以构建自己的自定义对话框容器。这通常用于显示AlertDialog而不是通用对话框;在这样做时,不需要实现onCreateView(LayoutInflater, ViewGroup, Bundle),因为AlertDialog会处理其自己的内容。

示例Dialog(在这种情况下是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();
    }
} 

setCanceble(boolean)属性表示您可以使用后退键退出Dialog。无需在任何地方捕获KEYCODE_BACK。


3
这样行不通。你需要在 DialogFragment 上调用 setCancelable(boolean),而不是像你现在做的那样在 Dialog 上调用。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接