i++

プログラム系のメモ書きなど

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;
}