2011年12月2日金曜日

ProgressDialog (円)

ダイアログはユーザーにメッセージを伝えたい場合に使いますが、作業中であることを示すものもあります。
前回は前者のAlertDialogを紹介しました。今回は後者のProgressDialogをご紹介しましょう。

ProgressDialogで作業中であることを表現する方法は2つあります。ひとつは、どれくらい時間がかかるかわからない、あるいはどれくらいの処理量があるかわからない場合に円を表示するもの(STYLE_SPINNER)、もうひとつは進捗率をバーで表示するもの(STYLE_HORIZONTAL)です。

まずは円のほうからサンプルを作って行きます。

Androidプロジェクトの設定
プロジェクト名:ProgressDialogTest1a
ビルドターゲット:Android 2.1-update1
アプリケーション名:ProgressDialogTest1a
パッケージ名:jp.co.triware.samples.ProgressDialogTest1a
アクティビティーの作成:ProgressDialogTest1aActivity
最小SDKバージョン:7
ProgressDialogのサンプルは全部で4つあります。プロジェクトの設定は適宜変更してください。

画面レイアウトはすべて同じものを使用します。

main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <Button
        android:id="@+id/start_btn"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Start ProgressDialog"
        />
</LinearLayout>
ボタンをクリックするとProgressDialogを表示します。

ProgresDialogTest1aActivity.java
package jp.co.triware.samples.ProgressDialogTest1a;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class ProgressDialogTest1aActivity extends Activity {
    private ProgressDialog mProgressDialog = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnStart = (Button)findViewById(R.id.start_btn);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // プログレスダイアログを生成
                mProgressDialog = new ProgressDialog(ProgressDialogTest1aActivity.this);
                // タイトルを設定
                mProgressDialog.setTitle("ProgressDialog");
                // スタイルを円形に設定
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                // メッセージを設定
                mProgressDialog.setMessage("しばらくお待ちください...");
                // Backボタンによるキャンセル可
                mProgressDialog.setCancelable(true);
                // キャンセル時に呼び出されるリスナーを設定
                mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        // ダイアログキャンセル時の処理
                        Toast.makeText(getApplicationContext(), "Cancelled.", Toast.LENGTH_SHORT).show();
                        mProgressDialog = null;
                    }
                });
                // ダイアログ終了時に呼び出されるリスナーを設定
                mProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        // 【注意】
                        // ダイアログが閉じる時に呼ばれるため、
                        // キャンセル時にも実行される。

                        // ダイアログ終了時の処理
                        Toast.makeText(getApplicationContext(), "Done.", Toast.LENGTH_SHORT).show();
                        mProgressDialog = null;
                    }
                });
                // ダイアログ表示
                mProgressDialog.show();
                // ダイアログ表示中の処理(別スレッドで実行)
                (new Thread(runnable)).start();
            }
        });
    }

    // 10秒後にダイアログを閉じる
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 100; i ++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    ;
                }
                if (mProgressDialog == null) {
                    // キャンセルされた場合はループ脱出
                    break;
                }
            }
            if (mProgressDialog != null) {
                // キャンセルされていなければダイアログを閉じる
                mProgressDialog.dismiss();
            }
        }
    };
}
ProgressDialogを10秒間表示するサンプルです。

28行目のmProgressDialog.setProgressStyle()でProgressDialogの種類(STYLE_SPINNER)を指定しています。

32行目のmProgressDialog.setCancelable(true);で、Backボタンを押した場合にキャンセルするようにしました。引数をfalseにすることでBackボタンを効かなくすることはできますが、処理に時間がかかるようなケースは、Backボタンや自分で作ったボタンでキャンセルできるようにしておくことが必要でしょう。

実行結果
ProgressDialog表示中、メッセージの左の円がくるくる回ります。

Backボタンでキャンセルすると、キャンセル処理に引き続き、終了処理も実行します。
10秒間待ってProgressDialogが閉じた場合は終了処理のみ実行します。

ProgressDialogTest1b.java
package jp.co.triware.samples.ProgressDialogTest1b;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class ProgressDialogTest1bActivity extends Activity {
    private ProgressDialog mProgressDialog = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnStart = (Button)findViewById(R.id.start_btn);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // プログレスダイアログを生成
                mProgressDialog = new ProgressDialog(ProgressDialogTest1bActivity.this);
                // タイトルを設定
                mProgressDialog.setTitle("ProgressDialog (Button)");
                // スタイルを円形に設定
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                // メッセージを設定
                mProgressDialog.setMessage("自動的にダイアログを閉じます...");
                // ボタンを設定(ボタンクリックでダイアログ終了)
                mProgressDialog.setButton(ProgressDialog.BUTTON_POSITIVE, "今すぐ閉じる", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // 既に閉じられている場合は何もしない
                        if (mProgressDialog == null) {
                            return;
                        }
                        // ダイアログ終了処理呼出
                        mProgressDialog.dismiss();
                    }
                });
                // Backボタンによるキャンセル可
                mProgressDialog.setCancelable(true);
                // キャンセル時に呼び出されるリスナーを設定
                mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        // 既に閉じられている場合は何もしない
                        if (mProgressDialog == null) {
                            return;
                        }
                        // ダイアログキャンセル時の処理
                        Toast.makeText(getApplicationContext(), "Cancelled.", Toast.LENGTH_SHORT).show();
                        mProgressDialog = null;
                    }
                });
                // ダイアログ終了時に呼び出されるリスナーを設定
                mProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                    @Override
                    public void onDismiss(DialogInterface dialog) {
                        // 既に閉じられている場合は何もしない
                        if (mProgressDialog == null) {
                            return;
                        }
                        // ダイアログ終了時の処理
                        Toast.makeText(getApplicationContext(), "Done.", Toast.LENGTH_SHORT).show();
                        mProgressDialog = null;
                    }
                });
                // ダイアログ表示
                mProgressDialog.show();
                // ダイアログ表示中の処理(別スレッドで実行)
                (new Thread(runnable)).start();
            }
        });
    }

    // 10秒後にダイアログを閉じる
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 100; i ++) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    ;
                }
                if (mProgressDialog == null) {
                    // 既に閉じられている場合はループ脱出
                    break;
                }
            }
            if (mProgressDialog != null) {
                // 閉じられていなければダイアログを閉じる
                mProgressDialog.dismiss();
            }
        }
    };
}
こちらは「今すぐ閉じる」ボタンを追加しました。

40行目でmProgressDialog.dismiss()を呼び出していますので、処理完了時にProgressDialogを閉じた場合と同じ機能になります。
Backボタンを押した時と同じ「キャンセル」扱いにしたい場合は、mProgressDialog.cancel()を呼び出します。

ProgressDialogTest1aからはキャンセル処理を改善しました。キャンセル処理が終わるとmProgressDialogにnullをセットしています(55行目)。終了処理ではmProgressDialogがnullであれば処理しないようにガード(63-65行目)するようにしましたので、キャンセル時に終了処理も実行するようなことはありません。


実行結果
「今すぐ閉じる」ボタンをクリックするとProgressDialog終了処理を実行します。

Backボタンでキャンセルしても、キャンセル処理だけ実行して終了処理は実行しません。


長くなってしまいましたので、続きは次回です。

0 件のコメント:

コメントを投稿