【Android】キャンセルボタン対応のProgressDialog
こんにちは。
前回のエントリーでDialogFragmentについて触れました。
この記事の中でProgressDialogを実装していますが、今回はこのProgressDialogにキャンセルボタンを付けたいと思います。
それでは早速コードを書きます。
なお、インスタンス生成時の引数でリスナーやタイトル等を設定するのと、これらをメンバ変数にし、Activity側でBundleにセットする方法の二つがあります(こちらのサイトでは、こちらの方法で実装しています)。 どちらがいいのかは分かりませんが、まぁ趣味ですかね。笑
今回は、インスタンス生成次の引数で設定する方法で書きたいと思います。 Activity側でBundleにセットする方法については、上記のサイト様にも書いてあるので、こちらを参考にしてください。
では、早速実装していきます。
まずはProgressDialogのDialogFragmentです。
public class MyProgressDialogFragment extends DialogFragment{ private static ProgressDialog progressDialog = null; private CancelListener listener; // リスナー用の変数です // インスタンス生成時にシリアライズ(リスナーを追加) public static MyProgressDialogFragment newInstance(String title, String message, Boolean cancel, Serializable Cancel_Listener){ MyProgressDialogFragment instance = new MyProgressDialogFragment(); // ダイアログにパラメータを渡す Bundle arguments = new Bundle(); arguments.putString("title", title); arguments.putString("message", message); arguments.putBoolean("cancel", cancel); if (cancel) // キャンセルの場合 arguments.putSerializable("Cancel_Listener", Cancel_Listener); instance.setArguments(arguments); return instance; } // キャンセルリスナ public interface CancelListener extends Serializable{ public void canceled(DialogInterface _interface); } // ProgressDialog作成 @Override public Dialog onCreateDialog(Bundle savedInstanceState){ if (progressDialog != null) return progressDialog; // パラメータを取得 String title = getArguments().getString("title"); String message = getArguments().getString("message"); Boolean cancel = getArguments().getBoolean("cancel", false); // リスナーを設定 listener = (CancelListener)getArguments().getSerializable("Cancel_Listener"); progressDialog = new ProgressDialog(getActivity()); progressDialog.setTitle(title); progressDialog.setMessage(message); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); // プログレスダイアログのスタイルを円スタイルに設定 // プログレスダイアログのキャンセルが可能かどうかを設定(バックボタンでダイアログをキャンセルできないようにする) setCancelable(cancel); if (cancel){ // キャンセルボタンありの場合はボタンを追加します。 progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "キャンセル", new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which){ listener.canceled(dialog); } }); } return progressDialog; } // progressDialog取得 @Override public Dialog getDialog(){ return progressDialog; } // ProgressDialog破棄 @Override public void onDestroy(){ super.onDestroy(); progressDialog = null; } // キャンセルのときに、リスナーに通知します。 @Override public void onCancel(DialogInterface dialog){ if (getArguments().getBoolean("cancel", false)){ listener.canceled(dialog); } } }
こんな感じです。 キャンセルボタンなしのときとの大きな違いは、リスナーを設定していることです。 これでActivity側にキャンセルボタンが押されたことを通知します。
次にActivity側です。 Activityでは、ボタンを押したらDialogを表示するようにします。
public class MainActivity extends Activity implements OnClickListener{ MyProgressDialogFragment progressDialog = null; // ロード中画面のプログレスダイアログ作成 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button)findViewById(R.id.button1); btn.setOnClickListener(this); } @Override public void onClick(View v) { // キャンセルリスナーの実装 @SuppressWarnings("serial") Serializable Cancel_Listener = new MyProgressDialogFragment.CancelListener() { @Override public void canceled(DialogInterface _interface) { Toast.makeText(MainActivity.this, "キャンセルされました", Toast.LENGTH_SHORT).show(); } }; progressDialog = MyProgressDialogFragment.newInstance("ネットワークに接続中です", "しばらくお待ちください", true, Cancel_Listener); progressDialog.show(getFragmentManager(), "progress"); if (progressDialog != null){ // Dialogが表示されている場合(なぜかisVisibleが使えなかったのでこっちで処理) Toast.makeText(this, "表示中", Toast.LENGTH_SHORT).show(); } } }
こんな感じです。
特に難しいことはしていませんが、キャンセルリスナーの実装のところだけ注意してください。
今回は無名関数でやっていますが、独自のリスナーを定義してやるのもありだと思います(前回の記事のAlertDialogではそのようにしています)。
また、DialogFragment#isVisible()でダイアログが表示中かどうかを取得できると思ったのですが、表示していてもしていなくてもFalseになってしまうので、null判定にしました。 今のところこれで出来ているので良いですが、なんで出来ないんですかね・・・
とりあえずこんな感じでキャンセルボタンに対応することが出来ました!
今回は以上です。 それでは。
2014年1月16日追記
ProgressDialogが表示中かどうかはgetShowsDialog()で取得できました。