如何使用ProgressDialog的替代方案(kotlin)

如何使用ProgressDialog的替代方案(kotlin)

情境

如何使用ProgressDialog中,示範了怎麼使用 ProgressDialog,但是 Google 官網 表示在 API 26 之後,就棄用了這個類別,原因出在因為 Android 不希望你的進度表會干擾到使用者操作頁面,建議是透過 ProgresBar 元件嵌在 XML 上,這篇教學將會提供兩個方法來示範替代方案,第一個是嵌入 XML 內,第二個是透過 AlertDialog 來做出我們的 ProgressDialog。

完整程式碼

你可以直接從 GitHub 直接觀看或下載程式碼。

程式碼說明

一開始會宣告兩個 Button,用來表示按下去會分別跳出 Progressbar 嵌入 Layout 以及 AlertDialog 的效果,透過這樣的方式來取代 ProgressDialog,可分別呈現兩種不同的效果。

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
 xmlns:tools="http://schemas.android.com/tools"  
 android:layout_width="match_parent"  
 android:layout_height="match_parent"  
 tools:context=".MainActivity">  

 <Button  android:id="@+id/show_dialog"  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content"  
  android:text="@string/show_loading_dilaog"/>  
 <Button  android:layout_below="@id/show_dialog"  
  android:id="@+id/start_progress"  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content"  
  android:text="@string/start_progress_loading"/>  
 <RelativeLayout  android:layout_centerInParent="true"  
  android:layout_width="match_parent"  
  android:layout_height="wrap_content">  
  <ProgressBar  style="@android:style/Widget.Material.ProgressBar.Large"  
   android:visibility="invisible"  
   android:id="@+id/progress"  
   android:layout_centerInParent="true"  
   android:layout_width="wrap_content"  
   android:layout_height="wrap_content"/>  
  <TextView  android:layout_marginEnd="5dp"  
   android:layout_centerInParent="true"  
   android:id="@+id/progress_msg"  
   android:layout_width="wrap_content"  
   android:layout_height="wrap_content"/>  
 </RelativeLayout>  
</RelativeLayout>

畫面如下圖所示。


一開始先呼叫嵌在 Layout 的 ProgressBar,在上面的 Layout 把它綁在畫面的中間,旁邊用一個 TextView 來顯示我們呈現的進度,透過這樣的方式來顯示跑的進度。
首先在宣告 XML 的時候,你會發現我們刻意調整 ProgressBar 的 style,其實這邊可以看到 Android 提供相當多的 style 給我們使用,因此,你可以根據不同的情境選擇你所需要的 ProgressBar style。


在程式中,我們透過第一個 Button 的事件點下的時候,宣告了一個 AlertDialog ,透過這個 AlertDialog 自定義畫面的方法,塞入了我們設定好了畫面如下,其中 ProgressBar 的 style 我們刻意選擇了水平的呈現方式。

<?xml version="1.0" encoding="utf-8"?>  
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
 android:layout_width="match_parent"  
 android:layout_height="match_parent">  
 <ProgressBar  android:layout_marginTop="30dp"  
  android:layout_marginStart="10dp"  
  android:layout_marginEnd="10dp"  
  style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"  
  android:visibility="invisible"  
  android:id="@+id/progress"  
  android:layout_centerVertical="true"  
  android:layout_width="100dp"  
  android:layout_height="wrap_content"/>  
 <TextView  android:layout_marginTop="10dp"  
  android:layout_marginStart="10dp"  
  android:layout_toEndOf="@id/progress"  
  android:id="@+id/progress_msg"  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content"/>  
</RelativeLayout>

接著透過程式來設定 AlertDialog。

show_dialog.setOnClickListener {  
 val view = LayoutInflater.from(this@MainActivity).inflate(R.layout.dialog_item, null)  
 showView(view)  
 AlertDialog  
  .Builder(this@MainActivity)  
  .setView(view)  
  .setPositiveButton("OK") { _, _ ->  
  }
  .show()  
}

這邊可以看一下 show 方法內的實作,這邊透過 Worker Thread 在背景假設運算,每次停留 100 毫秒,每次進度都加 1,並且透過 Main Thread 幫忙更新進度表跟文字。

private fun showView(view : View){  
 view.progress.visibility = VISIBLE  
 Thread {  
  for (i in 1..100) {  
   Thread.sleep(100)  
   runOnUiThread {  
   view.progress_msg.text = "$i%"  
   view.progress.progress = i  
   }  
  }  
  runOnUiThread{  
   view.progress_msg.text = "done."  
   view.progress.visibility = GONE  
  }  
 }.start()  
}

當按下第一個 show loading dialog 的 Button 結果如下圖所示,跳出一個 AlertDialog 裡面包著 ProgressBar 以及 TextView 顯示目前進度。


這樣就是一個簡單的 AlertDialog 取代 ProgressDialog 被棄用的替代方法了。
接下來試著用嵌入到畫面的方法來顯示進度表,在最上面的 Layout 中,我們有塞入了一個 ProgressBar,並且設定為隱藏,所以透過程式碼來顯示進度。

start_progress.setOnClickListener {  
 showView(window.decorView)  
}

當按下去第二個 start progress loading 的 Button 結果如下圖。


這樣就是一個簡單的 ProgressDialog 替代方案了。