我有一个简单的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();
}
}
答案 0 :(得分:44)
这可能与您的代码中没有显式调用cancel()
这一事实有关。
OnCancelListener文档说:
仅在取消对话框时调用
可能需要明确的cancel()
电话。
使用调用DialogInterface#cancel()
的OnClickListener
制作肯定/否定按钮,或使用OnDismissListener()
进行额外检查以查看是否点击了列表项。
此外,要收听后退按键并取消对话框,您可以设置OnKeyListener
,如this SO answer
此外,一旦设置了对话框,如果用户点击对话框外,最好使用Dialog#setCanceledOnTouchOutside()
。
编辑:以下部分是在DialogFragment中处理取消事件的简便方法。
由于您使用的是DialogFragment
,因此此类有一个非常方便的方法,DialogFragment#onCancel()
在取消DialogFragment
时会被调用。在那里做你的逻辑。
DialogFragments更复杂,生命周期与普通对话框略有不同。因此,如果您尝试将某个基于Dialog
的方法移植到DialogFragment
,请首先检查文档,可能存在一些允许新实现正常运行的方法!
答案 1 :(得分:11)
如果您使用 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;
}
});
答案 2 :(得分:9)
注意: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()
答案 3 :(得分:1)
实际上,如果您想使用DialogFragment
,则永远不能向其添加OnCancelListener
或OnDismissListener
,因为Dialog Fragment拥有对这些方法的回调!
这里有3个选项:
1-进入常规对话框。
2-将对话框片段设置为可取消(false)并在对话框中添加取消按钮。
3-检查@Nikhil Pingle答案。
这是来自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>
答案 4 :(得分:-1)
在DialogFragment中取消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
}
});