Android : DialogFragment で Back Key が押された際に確認のダイアログを表示する
何かを編集するダイアログで、変更を破棄してもよいかどうかを確認する場合などのパターンです。
ポイントは
- setCancelable(false) を呼んでキャンセルを無効にする
- Dialog のではなく、DialogFragment 自身の方を呼ぶ
- 全画面の style を設定している場合、画面外タッチによるキャンセルがないのであまり関係はない(onKey を上書きするので)
- Dialog#setOneKeyListener で KEYCODE_BACK に対する処理を追加する
- 何も変更がない場合など、確認の必要がなければすぐに DialogFragment#dismiss() を呼ぶ
- 確認が必要な場合はダイアログを表示し、OK が押された際に DialogFragment#dismiss() を呼ぶ
- 「キャンセルのキャンセル」等にわかりにくい文言ならないように注意
- 今回の文言は Evernote の文言を参考にした
DialogFragment を継承したクラスの onCreateDialog 部分
@NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.EditDialogTheme); View view = View.inflate(getActivity(), R.layout.fragment_edit, null); mEditText = (EditText) view.findViewById(R.id.edit_text); // mOriginalText は onCreate 等で設定しておく mEditText.setText(mOriginalText); builder.setView(view); Dialog dialog = builder.create(); setCancelable(false); dialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { // 変更なしなのでそのまま dismiss if (mMemoEditText.getText().toString().equals(mTopic.memo)) { dismiss(); } else { // 変更あり。確認を行う AlertDialog.Builder confirmDialogBuilder = new AlertDialog.Builder(getActivity()); confirmDialogBuilder.setTitle("変更を破棄しますか?"); confirmDialogBuilder.setMessage("変更が保存されていません。本当に変更部分を破棄してよろしいですか?"); confirmDialogBuilder.setNegativeButton(android.R.string.cancel, null); confirmDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dismiss(); } }); confirmDialogBuilder.create().show(); } return true; } return false; } }); return dialog; }