28

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

但是,如果我将对话框放入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();
    }
}
4

5 回答 5

54

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

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

这可能需要一个明确的cancel()调用。

OnClickListener要么使用 a调用一个正/负按钮,DialogInterface#cancel()要么使用OnDismissListener()带有额外检查的 a 来查看是否单击了列表项。

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

此外,一旦您设置了 Dialog,如果用户在 Dialog 之外点击,这也是一个好主意Dialog#setCanceledOnTouchOutside()

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

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

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

于 2013-02-09T16:31:28.190 回答
12

如果您正在使用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;
        }
    });
于 2013-09-09T18:16:52.517 回答
11

注意:DialogFragment 拥有 Dialog.setOnCancelListener 和 Dialog.setOnDismissListener 回调。你不能自己设置它们。

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

public class SelectItemDialog extends DialogFragment {

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

你应该删除 .setOnCancelListener()

于 2015-12-29T10:53:38.740 回答
1

实际上,如果您想使用DialogFragment,则永远无法添加OnCancelListenerOnDismissListener,因为 Dialog Fragment 拥有对这些方法的回调!

您在这里有 3 个选项:

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

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

 * <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>
于 2014-09-25T03:01:20.873 回答
-1

DialogFragment中的Cancel Listener或Dismiss listener可以通过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

                }

            });
于 2014-10-02T03:15:19.187 回答