いくつかの項目のリストを表示する単純なAlertDialog
があり、そのうちの1つをクリックすると、クリックされた項目は囲んでいる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();
}
}
コードからcancel()
への明示的な呼び出しがないという事実に関係している可能性があります。 OnCancelListener ドキュメンテーションは言う:
これはダイアログがキャンセルされたときにのみ呼び出されます
おそらく、明示的なcancel()
呼び出しが必要です。
DialogInterface#cancel()
を呼び出すOnClickListener
を使用して正/負のボタンを作成するか、 OnDismissListener()
を使用してリスト項目がクリックされたかどうかを確認する追加のチェック。
また、バックキーの押下をリッスンしてダイアログをキャンセルするには、 this SO answer で説明されているように、- OnKeyListener
を設定できます。 =
また、ダイアログを設定したら、ユーザーがダイアログの外側をタップした場合に備えて Dialog#setCanceledOnTouchOutside()
を使用することもお勧めします。
編集:以下の部分は、DialogFragmentでキャンセルイベントを処理する簡単な方法です。
DialogFragment
を使用しているため、このクラスには非常に便利なメソッド DialogFragment#onCancel()
があり、DialogFragment
がキャンセルされたときに呼び出されます。そこにあなたの論理を行います。
DialogFragmentsはより複雑で、通常のダイアログとはライフサイクルがわずかに異なります。したがって、最初にドキュメントを確認して、Dialog
に移植しようとしている特定のDialogFragment
ベースのアプローチがあるかどうかを確認します。新しい実装が適切に機能するためのメソッドがいくつか存在する可能性があります。
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;
}
});
注: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()を削除する必要があります
実際にDialogFragment
を使用する場合、OnCancelListener
またはOnDismissListener
を追加することはできません。DialogFragmentがこれらのメソッドへのコールバックを所有しているためです!
ここには3つのオプションがあります。
1-通常のダイアログを使用します。
2-ダイアログフラグメントをcancellable(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>