java DialogFragment 中未调用 OnCancelListener

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14790103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 17:24:33  来源:igfitidea点击:

OnCancelListener is not called in DialogFragment

javaandroidandroid-alertdialogandroid-dialogfragment

提问by Natix

I have a simple AlertDialogthat displays a list of some items and upon clicking one of them, the clicked item is passed back to the enclosing Activity. I also want to perform some default handling when the user cancels the dialog (using the back button) - more specifically, I want to pass an empty string to the activity in such case.

我有一个简单的AlertDialog显示一些项目的列表,单击其中一个后,单击的项目将传递回封闭的Activity. 我还想在用户取消对话框(使用后退按钮)时执行一些默认处理- 更具体地说,在这种情况下,我想将一个空字符串传递给活动。

However, if I put the dialog in a DialogFragment(from the compatibility package), the OnCancelListeneris not called when I close the dialog with the back button. What am I doing wrong?

但是,如果我将对话框放在 a DialogFragment(来自兼容包)中,OnCancelListener则当我使用后退按钮关闭对话框时不会调用。我究竟做错了什么?

public class SelectItemDialog extends DialogFragment {

    public interface Callback {
        void onItemSelected(String string);
    }

    private static final String ARG_ITEMS = "items";

    private Callback callback;

    public static SelectItemDialog fromItems(Collection<String> items) {
        SelectItemDialog fragment = new SelectItemDialog();
        fragment.setArguments(newArguments(items));
        return fragment;
    }

    private static Bundle newArguments(Collection<String> items) {
        Bundle arguments = new Bundle();
        arguments.putStringArray(ARG_ITEMS, items.toArray(new String[items.size()]));
        return arguments;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        callback = (Callback) activity;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final String[] items = getArguments().getStringArray(ARG_ITEMS);
        return new AlertDialog.Builder(getActivity())
            .setTitle(R.string.dialog_select_email_title)
            .setItems(items, new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    callback.onItemSelected(items[which]);
                }
            })
            .setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    // this code is not executed
                    callback.onItemSelected("");
                    throw new RuntimeException("dialog cancelled");
                }
            })
            .create();
    }
}

回答by A--C

It might have to do with the fact that there is no explicit call to cancel()from your code. The OnCancelListenerdocumentation says:

这可能与cancel()您的代码没有显式调用这一事实有关。该OnCancelListener文档说:

This will only be called when the dialog is canceled

这只会在对话框取消时调用

Which probably needs an explicit cancel()call.

这可能需要显式cancel()调用。

Either make a positive/negative button with a OnClickListenerthat calls DialogInterface#cancel()or use a OnDismissListener()with an extra check to see if a list item was clicked.

要么使用 aOnClickListener调用正/负按钮,DialogInterface#cancel()要么使用 aOnDismissListener()进行额外检查以查看是否单击了列表项。

Also, to listen for a back keypress and cancel the dialog, you can set up an OnKeyListener, like outlined in this SO answer

此外,要收听后退按键并取消对话,您可以设置一个OnKeyListener,如this SO answer中所述

Also, once you have the Dialog set up, it would also be a good idea to use Dialog#setCanceledOnTouchOutside()in case the the user taps outside the Dialog.

此外,一旦您设置了对话框,Dialog#setCanceledOnTouchOutside()在用户点击对话框之外的情况下使用它也是一个好主意。

Edit: The below part is the easy way to handle cancel events in a DialogFragment.

编辑:以下部分是在 DialogFragment 中处理取消事件的简单方法。

Since you are using a DialogFragment, this class has a very handy method, DialogFragment#onCancel()which gets called when the DialogFragmentis cancelled. Do your logic in there.

由于您使用的是DialogFragment,这个类有一个非常方便的方法,DialogFragment#onCancel()DialogFragment被取消时会被调用。在那里做你的逻辑。

DialogFragments are more complex, with a slightly different lifecycle than normal dialogs. Therefore, first check the documentation if you have a certain Dialog-based approach that you are trying to port to a DialogFragment, some methods may exist that allow your new implementation to function properly!

DialogFragments 更复杂,与普通对话框的生命周期略有不同。因此,如果您Dialog尝试移植到基于特定的方法,请首先检查文档DialogFragment,可能存在一些方法可以让您的新实现正常运行!

回答by Nikhil Pingle

If you are using DialogFragmentand want to listen back button then use this -

如果您正在使用DialogFragment并想收听返回按钮,请使用此 -

    this.getDialog().setOnKeyListener(new Dialog.OnKeyListener() {
        @Override
        public boolean onKey(DialogInterface dialog, int keyCode,
                KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (****) {
                    your logic
                }
                return true;
            }
            return false;
        }
    });

回答by Bao Le

Note: DialogFragment own the Dialog.setOnCancelListener and Dialog.setOnDismissListener callbacks. You must not set them yourself.

注意:DialogFragment 拥有 Dialog.setOnCancelListener 和 Dialog.setOnDismissListener 回调。您不得自行设置。

To find out about these events, override onCancel(DialogInterface) and onDismiss(DialogInterface).

要了解这些事件,请覆盖 onCancel(DialogInterface) 和 onDismiss(DialogInterface)。

public class SelectItemDialog extends DialogFragment {

    @Override
    public void onDismiss(DialogInterface dialog) {
        super.onDismiss(dialog);
        //your code hear
        dialog.cancel();
    }
}

And you should remove .setOnCancelListener()

你应该删除 .setOnCancelListener()

回答by Muhammad Alfaifi

Actually if you want to use DialogFragment, you can never add OnCancelListeneror OnDismissListenerto it, since the Dialog Fragment owns callbacks to these methods!

实际上,如果你想使用DialogFragment,你永远不能添加OnCancelListenerOnDismissListener到它,因为对话框片段拥有对这些方法的回调!

You have 3 options here:

您在这里有 3 个选择:

1- go with regular dialogs.
2- set your dialog fragment to cancellable(false) and add a cancel button to the dialog.
3- check @Nikhil Pingle answer.

1- 使用常规对话框。
2- 将您的对话框片段设置为可取消(false)并在对话框中添加一个取消按钮。
3- 检查@Nikhil Pingle 的答案。

this is from the documentation of the Dialog Fragment

这是来自对话框片段的文档

 * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener
 * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener
 * Dialog.setOnDismissListener} callbacks.  You must not set them yourself.</em>
 * To find out about these events, override {@link #onCancel(DialogInterface)}
 * and {@link #onDismiss(DialogInterface)}.</p>

回答by Munish Kapoor

Cancel Listener or Dismiss listener in DialogFragment can achieve by onDismiss

DialogFragment 中的 Cancel Listener 或 Dismiss 监听器可以通过 onDismiss 实现

            DialogFragment  newFragment = new DatePickerFragment();
            newFragment.show(getFragmentManager(), "datePicker");
            newFragment.onDismiss(new DialogInterface(){

                @Override
                public void cancel() {
                    // TODO Auto-generated method stub

                }

                @Override
                public void dismiss() {
                    // TODO Auto-generated method stub

                }

            });