ProgressDialog是AlertDialog的子類,我們用它來顯示有進度條的Dialog。這種帶有進度的UI控件在好多UI框架中都可以看到,當用戶執行一個操作時間較長的操作時,在一個設計良好的系統中應該要顯示一個進度條提示用戶目前處理的進度到哪了。在安裝應用程序和網絡交互應用中最常見到進度條,安裝應用程序由於耗時長,所以需要指示用戶進度,網絡交互由於網絡環境的不穩定也需要指示用戶交互的進度(尤其是當你在上傳或下載大文件時)。所以進度條是一個很常用到的控件。
Android爲我們提供了一個很好用的內置處理進度條的Dialog,它就是ProgressDialog。ProgressDialog裏的進度條分爲兩種:可確定值進度條和不可確定值進度條。可確定值進度條是指:系統能指示目前進度值,需要更新目前進度條的值,如果進度條到達一定值就表示完成進度。不可確定值進度條是指:系統指示需要等待,但是沒有給出目前進度,所以你無法得知目前進度到哪裏,只是能看到系統在處理,還需要等待的界面,所以說它沒有一個確定值。
我們來看一個最簡單的顯示ProgressDialog的代碼:
- ProgressDialog.show(this, "正在加載...", "系統正在處理您的請求");
上面代碼直接顯示了一個ProgressDialog,它是屬於不可確定值進度條的ProgressDialog,它的參數很簡單第一個參數是Context上下文信息,第二個參數是Dialog的title標題,第三個參數則是Dialog的body要顯示的信息,代碼的效果如下:
可以看到ProgressDialog顯示了一個在轉動的小圓圈,這個小圓圈將會永久轉動直到Dialog消失掉,所以這是一個不可確定值的進度條。運行代碼我們發現這個Dialog不可取消掉,它會一直存在直到你用代碼控制讓dialog消失,所以它是不可取消的,如果要讓用戶可以取消,要再後面添加兩個參數,分別是:
- ProgressDialog.show(this,
- "正在加載...", //標題
- "系統正在處理您的請求", //內容
- true, //是否不可確定值
- true);
上面使用show方法創建的不可確定值的ProgressDialog比較簡單,如果要創建一個可確定值的進度條dialog就會比較麻煩,因爲你需要編寫一些額外的代碼來控制進度條。這邊創建ProgressDialog就需要通過new 創建一個新對象,它沒有Builder可以通過配置來生成。所以我們要做的就是:
- 創建ProgressDialog對象
- 設置它內部的進度條是可確定值的
- 將它顯示出來
- 更新進度條值,當進度完成後隱藏對話框
我們根據上面這幾步,創建一個可複用的可確定值的ProgressDialog。首先我們要給需要managed的Dialog分配一個id值,然後重寫onCreateDialog方法創建ProgressDialog。
- @Override
- protected Dialog onCreateDialog(int id) {
- switch(id){
- case PROGRESS_DIALOG :
- ProgressDialog pd = new ProgressDialog(this);
- pd.setTitle("進度條"); //設置標題
- pd.setMessage("正在處理請稍後..."); //設置body信息
- pd.setMax(100); //進度條最大值是100
- pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //設置進度條樣式是 橫向的
- return pd;
- }
- return super.onCreateDialog(id);
- }
在這裏我們重寫Activity的onCreateDialog方法,讓ProgressDialog變成是可複用的managed dialog。當點擊按鈕時我們調用:
- showDialog(PROGRESS_DIALOG);
將onCreateDialog方法裏創建的ProgressDialog對象顯示出來:
上面就是可確定值進度條ProgressDialog的效果,可是它的進度條不會動,這是因爲你還沒用代碼去控制進度條的進度,所以這邊我們需要編寫一些額外代碼,當窗體顯示時首先讓進度條歸零,然後用一個線程讓進度條每100ms增加1,所以總共要10秒才能讀完整個進度條。我們用Handler對象來處理,因爲android中使用的是UI單線程模式,你自己創建線程不能訪問UI控件,否則會拋出異常。而Handler會將需要執行的代碼放到UI線程去執行。所以我們先定義一個Handler內部類來改變進度條的值。
- private static final int PROGRESS_DIALOG = 1;
- int progressValue = 0; //保存進度條目前的進度值,當達到最大值時隱藏ProgressDialog
- ProgressDialog mProgressDialog ; //引用的ProgressDialog對象
- Handler progressHandler;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.dialog3);
- progressHandler = new Handler(){
- public void handleMessage(android.os.Message msg) {
- if(progressValue == 100){
- mProgressDialog.dismiss();
- }else{
- //設置進度條的值加1
- progressValue ++;
- mProgressDialog.incrementProgressBy(1);
- //如果進度條還沒結束則100ms後進度條加1,循環調用每100ms就將進度條加1
- progressHandler.sendEmptyMessageDelayed(0, 100);
- }
- };
- };
- }
然後添加按鈕事件,當用戶點擊顯示可確定值ProgressDialog時,首先將進度條清0,然後發送第一條開始更新進度條的handler消息,因爲handler消息處理方法內部有循環調用發送消息,所以只要第一次觸發程序就會每100ms發送一個更新消息,直到進度條值到達100,隱藏掉對話框。所有代碼如下:
- <?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:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="顯示最簡單的ProgressDialog"
- android:onClick="onClick1"
- />
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="顯示可確定值的ProgressDialog"
- android:onClick="onClick2"
- />
- </LinearLayout>
- package com.king.dialog.uicontroller.dialog;
- import com.king.dialog.uicontroller.R;
- import android.app.Activity;
- import android.app.Dialog;
- import android.app.ProgressDialog;
- import android.os.Bundle;
- import android.os.Handler;
- import android.view.View;
- public class ProgressDialogActivity extends Activity {
- private static final int PROGRESS_DIALOG = 1;
- int progressValue = 0; //保存進度條目前的進度值,當達到最大值時隱藏ProgressDialog
- ProgressDialog mProgressDialog ; //引用的ProgressDialog對象
- Handler progressHandler;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.dialog3);
- progressHandler = new Handler(){
- public void handleMessage(android.os.Message msg) {
- if(progressValue == 100){
- mProgressDialog.dismiss();
- }else{
- //設置進度條的值加1
- progressValue ++;
- mProgressDialog.incrementProgressBy(1);
- //如果進度條還沒結束則100ms後進度條加1,循環調用每100ms就將進度條加1
- progressHandler.sendEmptyMessageDelayed(0, 100);
- }
- };
- };
- }
- public void onClick1(View view){
- ProgressDialog.show(this,
- "正在加載...", //標題
- "系統正在處理您的請求", //內容
- true, //是否不可確定值
- true); // 是否可取消
- }
- @Override
- protected Dialog onCreateDialog(int id) {
- switch(id){
- case PROGRESS_DIALOG :
- mProgressDialog = new ProgressDialog(this);
- mProgressDialog.setTitle("進度條"); //設置標題
- mProgressDialog.setMessage("正在處理請稍後..."); //設置body信息
- mProgressDialog.setMax(100); //進度條最大值是100
- mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //設置進度條樣式是 橫向的
- return mProgressDialog;
- }
- return super.onCreateDialog(id);
- }
- public void onClick2(View view){
- showDialog(PROGRESS_DIALOG);
- progressValue = 0;
- mProgressDialog.setProgress(0);
- progressHandler.sendEmptyMessage(0);
- }
- }
代碼運行效果如下:
用戶可以看到在走動的進度條,當進度條達到100時ProgressDialog就自動消失。這邊一個難點就是Handler的用法,這個以後會再仔細介紹,現在先了解Handler就是可以將代碼放到UI線程去執行即可。