昔のAndroidではProgressDialogが使えました。
▼ こんな用途にとても便利だった
- 現在の進捗パーセントを表示したり、
- 進捗プログレスバーも表示できる
ただ今はProgressDialogは非推奨です。
でもプログレスダイアログが表示したいので、
AndroidでProgressDialogを独自実装してみました。
このページの目次
APIレベル26からProgressDialogは非推奨
非推奨になったのはAPIレベル26から
Android8.0 = Oreoからですね。
▼ ProgressDialog | Android Developers
This class was deprecated in API level 26.
ProgressDialog is a modal dialog, which prevents the user from interacting with the app. Instead of using this class, you should use a progress indicator like ProgressBar, which can be embedded in your app's UI. Alternatively, you can use a notification to inform the user of the task's progress.引用元 : https://developer.android.com/reference/android/app/ProgressDialog
▼ 上記リファレンスの意訳
このクラスはAPIレベル26から非推奨になりました。ProgressDialogはモーダルダイアログであり、それはユーザーの操作を妨げてしまいます。これを使う代わりに、アプリUIに埋め込まれたプログレスメーターを使うべきです。あるいはタスク進捗の表示に通知を使うとか
引用元 : https://developer.android.com/reference/android/app/ProgressDialog
これを使うのはUI的にダメみたいです。
でもProgressDialogは進捗を分かりやすく表示できます。もし通知バーだと見逃されたり無効化されるかもしれません。
だからProgressDialogを独自実装しました。
1.ProgressDialog用レイアウト作成
初めにしたのがレイアウトの作成です。
▼ レイアウトに含まれる内容
- 進捗表示のProgressBar
- 進捗を表示するTextView
▼ 作成したレイアウト
▼ 名前は dialog_progress.xml とした
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <ProgressBar android:id="@+id/progress_bar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/progress_1_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="0%" /> <TextView android:id="@+id/progress_2_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="right" android:text="0/100" /> </LinearLayout> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> |
これはそのままコピペでOKです。
2.DialogFragmentからProgressDialog定義
次にProgressDialog本体を定義します。
DialogFragmentを拡張して作りました。
▼ こんな内容(ProgressDialog.kt)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
class ProgressDialog : DialogFragment() { private lateinit var progressBar: ProgressBar private lateinit var progress1TextView: TextView private lateinit var progress2TextView: TextView companion object { fun newInstance( title: String, message: String, cancelableOutsideTouch: Boolean=true ): ProgressDialog { val instance = ProgressDialog() val arguments = Bundle() arguments.putString("message", message) arguments.putString("title", title) arguments.putBoolean("cancelableOutsideTouch", cancelableOutsideTouch) instance.arguments = arguments return instance } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { /// タイトル val title = requireArguments().getString("title") /// メッセージ val message = requireArguments().getString("message") /// 外側タッチで閉じれるかどうか val cancelableOutsideTouch = requireArguments().getBoolean("cancelableOutsideTouch") /// レイアウトからダイアログ作成 val builder = AlertDialog.Builder(requireActivity()) val inflater = requireActivity().layoutInflater val view = inflater.inflate(R.layout.dialog_progress, null) progressBar = view.findViewById(R.id.progress_bar) progress1TextView = view.findViewById(R.id.progress_1_text_view) progress2TextView = view.findViewById(R.id.progress_2_text_view) builder.setTitle(title) builder.setMessage(message) builder.setView(view) val dialog = builder.create() dialog.setCanceledOnTouchOutside(cancelableOutsideTouch) return dialog } /// 現在の進捗パーセントを更新 fun setProgress(progress: Int){ if(this::progressBar.isInitialized) { progressBar.progress = progress progress1TextView.text = "${progress}%" progress2TextView.text = "${progress}/100" } } } |
ほとんど説明はいらないと思います。
独自ダイアログを作りたいなら独自レイアウトを定義し、DialogFragmentを拡張するのが王道です。コード量もそこまで多くありません。
これで自作ProgressDialogの完成です。
3.進捗を独自ProgressDialogで表示
実際にProgressDialogを表示してみます。
▼ 模擬的なコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
/// ProgressDialogの生成 val cancelableOutsideTouch = false val progressDialog = ProgressDialog.newInstance( "ダウンロード中", "アプリを閉じないでください", cancelableOutsideTouch) /// ProgressDialog表示 progressDialog.show(supportFragmentManager, TAG) /// ファイルをダウンロードする模擬コード /// Fuelライブラリの詳細は別記事参照 val downloadUrl = "https://hoge.com/hugefile" Fuel.download(downloadUrl) .fileDestination { response, url -> /// } .progress { readBytes, totalBytes -> /// ダウンロード進捗が変化した場合 /// ProgressBarの進捗更新 val progress = readBytes.toFloat() / totalBytes.toFloat() * 100 runOnUiThread { /// UIスレッドでProgressBar更新 progressDialog.setProgress(progress.toInt()) } } .response { result -> result.fold( success = { /// ダウンロード完了 }, failure = { /// ダウンロード失敗 } ) runOnUiThread { /// ProgressBar閉じる progressDialog.dismiss() } } |
上記コードではFuelライブラリを使ってます。
▼ KotlinからRest APIを数行コードで呼び出し
それで上記ライブラリで数百MBのファイルのダウンロードなどを想定し、進捗が進むごとにProgressDialogで進捗バー・テキストを表示するコードを書きました。
実際に表示できるProgressDialogの見た目
どういった見た目になったかを載せときます。
▼ 進捗0%のときのProgressDialog
▼ 進捗38%のときのProgressDialog
▼ 進捗100%のときのProgressDialog
タイトルやメッセージも自由にカスタマイズ可能。
むしろ既存のProgressDialogより便利かもしれません。
自前のProgressDialog実装が難しくない
ここまでの流れをまとめると次の通り
手順を1つ1つ踏んでいけば難しくありません。
以上、ProgressDialog自前実装でした。ではまた