Android筆記(17):UI元件 ProgressBar 進度桿

Photo by lilzidesigns on Unsplash


在 Android 中,提供了 ProgressBar 進度條 、SeekBar 拖動條和 RatingBar 評分條等元件。若要呈現某作業的完成進度百分比,可使用 ProgressBar 元件表示,若要使用者透過拖動滑塊來改變值或進度的元件稱為 SeekBar 元件,而使用星星圖案表示進度的元件稱為 RatingBar,一般作為給予評分用的會使用 RatingBar。本篇先來瞭解如何使用 ProgressBar。

[ProgressBar]

當一個 APP 在背景執行時,例如下載檔案或系統更新,使用者介面上是不會有任何資訊的,使用者不知道背景程式何時會結束,也不知道執行的進度及回應狀況,這時會使用 ProgressBar 來讓使用者知道執行的進度。當 ProgressBar 進度到了最右邊時,表示這項工作完成。在 Android 的 XML 佈局檔中使用 <ProgressBar>作為標記新增 ProgressBar,基本語法格式如下:
<ProgressBar
   android:屬性 = "值"> 
</ProgressBar>

ProgressBar 元件繼承自 View,因此 ProgressBar 可以使用 View 相關的屬性,除了 View 可用的屬性外,還有以下幾種:
XML屬性描 述
max設定 ProgressBar 的最大值。
progress設定 ProgressBar 已完成的進度值。
progressDrawable設定 ProgressBar 軌道的繪製形式。
indeterminate是否顯示不確定模式,預設為 true。
style設定 ProgressBar 的外觀樣式。

style 的撰寫方式跟一般的屬性有點不同,寫法如下:
    <ProgressBar
        android:layout_width= "wrap_content"
        android:layout_height= "wrap_content"
        style= "@android:style/Widget.ProgressBar.Horizontal" />
在 Android 中,提供了兩種 ProgressBar的 style 屬性:水平及圓形的樣式,預設為圓形的 ProgressBar。者兩種的樣式又可分成大小等不同樣式,style 可設定的屬性如下:
XML屬性描述
?android:attr/progressBarStyleHorizontal 細水平長條 ProgressBar
?android:attr/progressBarStyleLarge 大圓形 ProgressBar
?android:attr/progressBarStyleSmall小圓形 ProgressBar
@android:style/Widget.ProgressBar.Horizontal粗水平長條 ProgressBar
@android:style/Widget.ProgressBar.Large 大跳躍、旋轉畫面的 ProgressBar
@android:style/Widget.ProgressBar.Small小跳躍、旋轉畫面的 ProgressBar
@android:style/Widget.ProgressBar.Inverse大跳躍、反白旋轉畫面的 ProgressBar

上表的各種 Style 樣式呈現的結果如下:

ProgressBar 元件還提供了下面兩個常用方法用於操作進度:
  • setProgress(int progress) 方法:用於設置進度完成的百分比。
  • incrementProgressBy(int diff) 方法:用於設置進度條的進度增加或減少。當參數值為正數時, 表示進度增加;當參數值為負數時,表示進度減少。

以下程式範例使用執行緒的方式搭配數字百分比來呈現 ProgressBar 進度。


[程式範例]

(1)新建一個模組 Module,進入 res/layout 目錄下點選佈局檔 activity_main.xml。將預設的內容刪除,建立 1 個 TextView 文字框,1 個 ProgressBar,以及 1 個 Button 按鈕,以下是完整 XML 的內容。
<LinearLayout 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"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/pcnt"
        android:layout_width="wrap_content"
        android:layout_marginTop="50sp"
        android:layout_gravity="center_horizontal"
        android:layout_height="50sp"
        android:textColor="#FFDD5500"
        android:text=""
        android:textSize="30dp" />

    <ProgressBar
        android:id="@+id/pb"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="50sp"
        android:max="100" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20sp"
        android:onClick="download"
        android:text="Download" />

</LinearLayout>

(2)在 MainActivity.java 在 onCreate() 方法內,先建立與佈局檔的物件,用 findValueById 連結元件,在下載的按鈕建立一個 onClick() 程序,讓這個程序呼叫建立執行緒,執行緒內建立迴圈每 1.5 秒檢查是否已經超過 100,如果還沒超過,會呼叫 MyHandler 類別,顯示數字百分比在 TextView 上。程式碼如下:
package com.example.myprogressbar;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.TextureView;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

public class pb_MainActivity extends AppCompatActivity {

    private int pg = 0;
    private ProgressBar pb;
    private TextView pcnt;
    private MyHandler myHandler = new MyHandler();  // 建立一個新的 Handler 類別

    public class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case 1:
                    pg++;
                    pb.setProgress(pg);    //  給 ProgressBar 當前的進度值
                    pcnt.setText(pg + "%");  // 顯示當時的進度值
                    break;
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pb_main);

        pb = (ProgressBar) findViewById(R.id.pb);
        pcnt = (TextView) findViewById(R.id.pcnt);
    }

    // 點擊 Download 按鈕
    public void download(View v) {
        if(pg == 0){   //當進度為 0 時
            new myThread().start();  //建立多線程 Thread 程序
        }
    }

    public class myThread extends Thread{
        @Override
        public void run() {
            super.run();
            while(true){
                try {
                    Thread.sleep(150);    // 暫停 0.15 秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if(pg >= 100){  //若超過 100 時,離開程式
                    pg = 0;
                    break;
                }

                Message msg=new Message();
                msg.what=1;
                myHandler.sendMessage(msg);  // 代碼傳給 Handler 
            }
        }
    }
}

執行的結果如下:

[參考資料]


Post a Comment

較新的 較舊