Furudateのブログ

プログラミングやネットワーク系の知識・技術がメインのブログ。技術メモ帳的な感じになるかと。岩手から発信していきます。

【Android】DialogFragmentを使ってみる

こんにちは。

前回、こちらのエントリーでAlertDialogについて触れました。

このエントリーの最後にも書いてあるのですが、現在はDialogFragmentが推奨されており、こちらを使うのが良いようです。

そこで、今回はこれを使ってAlertDialogとProgressDialogを出してみたいと思います。 最初は癖がありますが、慣れるとそれほど難しくありません。

AlertDialogを出す

まずはAlertDialogです。 はじめに、DialogFragmentを継承するクラスを作成します。

なお、今回はOKボタンやCancelボタンが押されたかのイベントをActivity側に返すために、Listenerを作成しています。

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
// ここは要注意。
// import android.support.v4.app.DialogFragment;だとうまくいかないので、必ず以下にする。
import android.app.DialogFragment;

public class MyDialogFragment extends DialogFragment{
    private DialogListener listener = null;
    /**
    * ファクトリーメソッド
    * @param type ダイアログタイプ 0:OKボタンのみ 1:OK, NGボタン
    */
    public static MyDialogFragment newInstance(String title, String message, int type){
        MyDialogFragment instance = new MyDialogFragment();
        
        // ダイアログに渡すパラメータはBundleにまとめる
        Bundle arguments = new Bundle();
        arguments.putString("title", title);
        arguments.putString("message", message);
        arguments.putInt("type", type);
        
        instance.setArguments(arguments);
        
        return instance;
    }
    
    /**
    * AlertDialog作成
    */
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState){
        String title = getArguments().getString("title");
        String message = getArguments().getString("message");
        int type = getArguments().getInt("type");
        
        AlertDialog.Builder alert = new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // OKボタンが押された時
                    listener.doPositiveClick();
                    dismiss();
                }
            });
        if (type == 1){ // NGボタンも付ける場合
            alert.setNegativeButton("キャンセル", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // Cancelボタンが押された時
                    listener.doNegativeClick();
                    dismiss();
                }
            });
        }
        
        return alert.create();
    }
    
    /**
    * リスナーを追加
    */
    public void setDialogListener(DialogListener listener){
        this.listener = listener;
    }
    
    /**
    * リスナー削除
    */
    public void removeDialogListener(){
        this.listener = null;
    }
}

注意してほしいのはコード上にも書きましたが、インポートの部分です。 それ以外は難しいことはしていません。 そして、リスナーで対象Activityのリスナーをセットしています。

次にそのリスナーインターフェースを作成します。

import java.util.EventListener;

public interface DialogListener extends EventListener{

    /**
     * OKボタンが押されたイベントを通知
     */
    public void doPositiveClick();
    
    /**
     * Cancelボタンが押されたイベントを通知
     */
    public void doNegativeClick();
}

ここは特に何もありません。 次に行きます。

次はActivity側です。 Activityではダイアログを表示するShow関数、OKボタン、Cancelボタンが押された時の処理をする関数をそれぞれ定義します。 以下のコードでは、これらの関数の定義部分以外は省略します。

public class MainActivity extends Activity implements DialogListener{ // DialogListener をImplementsしておくこと
     /**
     * ダイアログ表示関数
     * @param type ダイアログタイプ 0:OKボタンのみ 1:OK, NGボタン
     */
    public void showDialog(String title, String message, int type){
        MyDialogFragment newFragment = MyDialogFragment.newInstance(title, message, type);
        // リスナーセット
        newFragment.setDialogListener(this);
        // ここでCancelable(false)をしないと効果が無い
        newFragment.setCancelable(false);
        newFragment.show(getFragmentManager(), "dialog");
    }
    
    /**
     * OKボタンをおした時
     */
    public void doPositiveClick() {
        finish();
    }

    /**
     * NGボタンをおした時
     */
    @Override
    public void doNegativeClick() {

    }
}

注意点としては、以下のとおりです。

  • DialogListenerをImplementsしておくこと
  • バックボタンなどでアラートを閉じさせたくない時には、DialogFragment#setCancelable()をしないと動かないので、Activity側で呼び出すようにすること(MyDialogFragmentの中でやっても意味ない)

あとはアラートダイアログを表示させたい場所でshowDialog()を呼び出せばOKです。

ProgressDialogを出す

次にProgressDialogです。 前にこちらのエントリーでProgressDialogの出し方を書きましたが、これをDialogFragmentで出したいと思います。

今回は、円スタイルのDialogにします。 プログレスバーの方のやり方は後々書ければ書きたいと思いますが、参考サイトにも書いてあるし、やり方もあまり変わらないので特に問題ないとは思います。

それでは早速コードです。 分かりやすいように、上のAlertDialogのDialogFragmentとは別のFragmentを作成します。

import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.os.Bundle;

public class MyProgressDialogFragment extends DialogFragment{
    private static ProgressDialog progressDialog = null;
    
    // インスタンス生成はこれを使う
    public static MyProgressDialogFragment newInstance(String title, String message){
        MyProgressDialogFragment instance = new MyProgressDialogFragment();
        
        // ダイアログにパラメータを渡す
        Bundle arguments = new Bundle();
        arguments.putString("title", title);
        arguments.putString("message", message);
        
        instance.setArguments(arguments);
        
        return instance;
    }
    
    // ProgressDialog作成
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState){
        if (progressDialog != null)
            return progressDialog;
        
        // パラメータを取得
        String title = getArguments().getString("title");
        String message = getArguments().getString("message");
        
        progressDialog = new ProgressDialog(getActivity());
        progressDialog.setTitle(title);
        progressDialog.setMessage(message);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); // プログレスダイアログのスタイルを円スタイルに設定
        // プログレスダイアログのキャンセルが可能かどうかを設定(バックボタンでダイアログをキャンセルできないようにする)
        setCancelable(false);
        
        return progressDialog;
    }
    
    // progressDialog取得
    @Override
    public Dialog getDialog(){
        return progressDialog;
    }
    
    // ProgressDialog破棄
    @Override
    public void onDestroy(){
        super.onDestroy();
        progressDialog = null;
    }
}

以上です。

基本的にAlertDialogのFragmentと違いはありません。 注意すべきところとして、onDestroy()をOverrideしておかないと、Dismissしたときに落ちるので、必ずするようにしましょう。

そして、使いたいActivityなどで以下のようにして呼び出します。

MyProgressDialogFragment progressDialog;   // ロード中画面のプログレスダイアログ作成

progressDialog = MyProgressDialogFragment.newInstance("ネットワークに接続中です", "しばらくお待ちください");
// Dialog表示
progressDialog.show(getFragmentManager(), "progress");

// Dialog終了
progressDialog.getDialog().dismiss();

こんな感じです。簡単ですね。 Dialogを終了するとき、getDialog()してからdismiss()するようにしないと落ちるので気をつけてください。

以上です。 これでDialogFragmentに対応することが出来たかなと思います。 少し癖があるように感じますが、慣れるとそれほど難しくはなさそうです。 Dialogに関しては、Fragmentを推奨しているので、積極的に使っていきましょう。

それでは。

参考にさせていただいたサイト

DialogFragment | Android Developers
DialogFragmentでシンプルで汎用的なダイアログ
Code
DialogFragmentではsetCancelableはフラグメントに対して行う
画面回転、キャンセル対応のProgress DialogFragment
DialogFragment の dismiss で落ちる