OnCancelListener не вызывается в DialogFragment
У меня есть простой 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();
}
}
Ответы
Ответ 1
Возможно, это связано с тем, что явный вызов cancel()
из вашего кода отсутствует.
Документация OnCancelListener гласит:
Это будет вызываться только при отмене диалога
Кому, вероятно, нужен явный вызов cancel()
.
Либо создайте положительную/отрицательную кнопку с OnClickListener
, которая вызывает DialogInterface#cancel()
или используйте OnDismissListener()
с дополнительной проверкой, чтобы увидеть, был ли нажат элемент списка.
Кроме того, чтобы прослушать обратное нажатие и отменить диалог, вы можете настроить OnKeyListener
, как описано в этот ответ SO
Кроме того, как только вы установили Dialog, было бы неплохо использовать Dialog#setCanceledOnTouchOutside()
в случае, если пользователь выходы за пределы диалогового окна.
Изменить: нижняя часть - это простой способ обработки событий отмены в диалоговом окне диалога.
Поскольку вы используете DialogFragment
, этот класс имеет очень удобный метод, DialogFragment#onCancel()
, который вызывается, когда DialogFragment
отменяется. Сделайте свою логику там.
Диалоговые фрагменты более сложные, с немного иным жизненным циклом, чем обычные диалоги. Поэтому сначала проверьте документацию, если у вас есть определенный подход Dialog
, который вы пытаетесь подключить к DialogFragment
, могут существовать некоторые методы, которые позволят вашей новой реализации правильно функционировать!
Ответ 2
Если вы используете 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;
}
});
Ответ 3
Примечание. 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()
Ответ 4
На самом деле, если вы хотите использовать DialogFragment
, вы никогда не сможете добавить к нему OnCancelListener
или OnDismissListener
, так как фрагмент диалога владеет обратными вызовами этих методов!
У вас есть 3 варианта:
1- перейдите с регулярными диалогами.
2- установите фрагмент диалога на отмену (false) и добавьте кнопку отмены в диалог.
3- проверить @Ответ Нихиль Пингл.
это из документации фрагмента диалога
* <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>
Ответ 5
Отмена прослушивателя или отклонения слушателя в DialogFragment может быть достигнуто 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
}
});