DialogFragmentのキャンセルを無効にする


DialogFragmentでキャンセル操作を無効化する方法を紹介します。Backキーや画面外のタップなどがキャンセル操作にあたります。DialogFragment#setCancelableメソッドを利用します。onCreateDialogメソッド内で生成したDialogに対して直接setCancelableを指定しても効かないため注意してください。

device-2014-08-11-003345 device-2014-08-11-002548
ダイアログ表示前 ダイアログ(キャンセル無効)

キャンセルを無効にするとBackキーや画面外のタップが効かなくなります。ユーザーがOKを押すまで画面を表示し続けられるというメリットがありますが、Android標準の挙動とは異なることを十分考慮しましょう。

サンプルコードは続きから

DialogFragmentを表示する

次のサンプルコードは、Activityで表示したボタンを押すとダイアログが現れるようになっています。

■src/MainActivity.java

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button b = (Button) findViewById(R.id.button);
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                MyDialogFragment dialog = new MyDialogFragment();
                dialog.show(getSupportFragmentManager(),"dialog");
            }
        });
    }
    ...省略...
}

ボタンを押すとDialogFragmentを継承したMyDialogFragmentを表示しています。

DialogFragment#setCancelableでキャンセルを無効にする

MyDialogFragmentでは、DialogFragment#onCreateDialogメソッドで表示するダイアログを作成します。

public class MyDialogFragment extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // ダイアログ生成
        AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
        dialog.setTitle("DialogFragment Title");
        dialog.setMessage("Message");
        dialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                // do nothing.
                Log.d("MyDialogFragment", "onClick");
            }
        });
        this.setCancelable(false); // DialogFragment#setCancelableを使用すること
        return dialog.create();
    }
    ...省略...
}

サンプルコードのDialogFragment#onCreateDialogメソッドでは、AlertDialog.Builderを使ってDialogのインスタンスを生成しています。
キャンセルを無効にするためには、16行目のとおりDialogFragment#setCancelableを使用してください。

Dialogに対してタイトル、メッセージを設定しているため、Dialog#setCancelableを使ってしまいそうになりますが、
DialogFragmentでは、Dialog#setCancelableの結果は反映されません。

リファレンスにもDialogFragmentでは、Dialog.setCancelableを直接呼ぶ代わりにDialogFragment#setCancelableを使用する(こちらに基づいて制御されている)旨が記載されています。

Control whether the shown Dialog is cancelable. Use this instead of directly calling Dialog.setCancelable(boolean), because DialogFragment needs to change its behavior based on this.

以上、おつかれさまでした。