ProgressDialog是AlertDialog的子类,我们用它来显示有进度条的Dialog。这种带有进度的UI控件在好多UI框架中都可以看到,当用户执行一个操作时间较长的操作时,在一个设计良好的系统中应该要显示一个进度条提示用户目前处理的进度到哪了。在安装应用程序和网络交互应用中最常见到进度条,安装应用程序由于耗时长,所以需要指示用户进度,网络交互由于网络环境的不稳定也需要指示用户交互的进度(尤其是当你在上传或下载大文件时)。所以进度条是一个很常用到的控件。

Android为我们提供了一个很好用的内置处理进度条的Dialog,它就是ProgressDialog。ProgressDialog里的进度条分为两种:可确定值进度条和不可确定值进度条。可确定值进度条是指:系统能指示目前进度值,需要更新目前进度条的值,如果进度条到达一定值就表示完成进度。不可确定值进度条是指:系统指示需要等待,但是没有给出目前进度,所以你无法得知目前进度到哪里,只是能看到系统在处理,还需要等待的界面,所以说它没有一个确定值。

我们来看一个最简单的显示ProgressDialog的代码:


[c-sharp] view plain copy print ?

1. ProgressDialog.show(this, "正在加载...", "系统正在处理您的请求");

ProgressDialog.show(this, "正在加载...", "系统正在处理您的请求");

上面代码直接显示了一个ProgressDialog,它是属于不可确定值进度条的ProgressDialog,它的参数很简单第一个参数是Context上下文信息,第二个参数是Dialog的title标题,第三个参数则是Dialog的body要显示的信息,代码的效果如下:

可以看到ProgressDialog显示了一个在转动的小圆圈,这个小圆圈将会永久转动直到Dialog消失掉,所以这是一个不可确定值的进度条。运行代码我们发现这个Dialog不可取消掉,它会一直存在直到你用代码控制让dialog消失,所以它是不可取消的,如果要让用户可以取消,要再后面添加两个参数,分别是:


[c-sharp] view plain copy print ?



    1. ProgressDialog.show(this,  
    2. "正在加载...", //标题
    3. "系统正在处理您的请求", //内容
    4. true, //是否不可确定值
    5. true);


    ProgressDialog.show(this, "正在加载...", //标题 "系统正在处理您的请求", //内容 true, //是否不可确定值 true);

    上面使用show方法创建的不可确定值的ProgressDialog比较简单,如果要创建一个可确定值的进度条dialog就会比较麻烦,因为你需要编写一些额外的代码来控制进度条。这边创建ProgressDialog就需要通过new 创建一个新对象,它没有Builder可以通过配置来生成。所以我们要做的就是:

    1. 创建ProgressDialog对象
    2. 设置它内部的进度条是可确定值的
    3. 将它显示出来
    4. 更新进度条值,当进度完成后隐藏对话框

    我们根据上面这几步,创建一个可复用的可确定值的ProgressDialog。首先我们要给需要managed的Dialog分配一个id值,然后重写onCreateDialog方法创建ProgressDialog。


    [c-sharp] view plain copy print ?


    1. @Override  
    2. protected Dialog onCreateDialog(int
    3.    
    4. switch(id){  
    5.    
    6. case
    7. new ProgressDialog(this);  
    8. "进度条");    //设置标题
    9. "正在处理请稍后..."); //设置body信息
    10. //进度条最大值是100
    11. //设置进度条样式是 横向的
    12.    
    13. return
    14.    
    15.     }  
    16.    
    17. return
    18. }


    @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。当点击按钮时我们调用:


    [c-sharp] view plain copy print ?


    1. showDialog(PROGRESS_DIALOG);


    将onCreateDialog方法里创建的ProgressDialog对象显示出来:

    上面就是可确定值进度条ProgressDialog的效果,可是它的进度条不会动,这是因为你还没用代码去控制进度条的进度,所以这边我们需要编写一些额外代码,当窗体显示时首先让进度条归零,然后用一个线程让进度条每100ms增加1,所以总共要10秒才能读完整个进度条。我们用Handler对象来处理,因为android中使用的是UI单线程模式,你自己创建线程不能访问UI控件,否则会抛出异常。而Handler会将需要执行的代码放到UI线程去执行。所以我们先定义一个Handler内部类来改变进度条的值。


    [c-sharp] view plain copy print ?



    1. private static final int
    2.    
    3. int progressValue = 0;  //保存进度条目前的进度值,当达到最大值时隐藏ProgressDialog
    4. ProgressDialog mProgressDialog ; //引用的ProgressDialog对象
    5. Handler progressHandler;  
    6.    
    7. @Override  
    8. protected void
    9.     super.onCreate(savedInstanceState);  
    10.    
    11.     setContentView(R.layout.dialog3);  
    12.    
    13. new
    14.    
    15. public void
    16.    
    17. if(progressValue == 100){  
    18.                 mProgressDialog.dismiss();  
    19. else{   
    20. //设置进度条的值加1
    21.                 progressValue ++;  
    22.                 mProgressDialog.incrementProgressBy(1);  
    23. //如果进度条还没结束则100ms后进度条加1,循环调用每100ms就将进度条加1
    24.                 progressHandler.sendEmptyMessageDelayed(0, 100);   
    25.             }  
    26.    
    27.         };  
    28.    
    29.     };  
    30.    
    31. }



    然后添加按钮事件,当用户点击显示可确定值ProgressDialog时,首先将进度条清0,然后发送第一条开始更新进度条的handler消息,因为handler消息处理方法内部有循环调用发送消息,所以只要第一次触发程序就会每100ms发送一个更新消息,直到进度条值到达100,隐藏掉对话框。所有代码如下:


    
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout  
    3. "http://schemas.android.com/apk/res/android"
    4. "vertical"
    5. "fill_parent"
    6. "fill_parent">  
    7.    
    8.   <Button  
    9. "wrap_content"
    10. "wrap_content"
    11. "显示最简单的ProgressDialog"
    12. "onClick1"
    13.   />  
    14.    
    15.   <Button  
    16. "wrap_content"
    17. "wrap_content"
    18. "显示可确定值的ProgressDialog"
    19. "onClick2"
    20.   />  
    21.    
    22. </LinearLayout>


    1. package com.king.dialog.uicontroller.dialog;   
    2.    
    3. import com.king.dialog.uicontroller.R;  
    4.    
    5. import android.app.Activity;  
    6. import android.app.Dialog;  
    7. import android.app.ProgressDialog;  
    8. import android.os.Bundle;  
    9. import android.os.Handler;  
    10. import android.view.View;  
    11.    
    12. public class
    13.    
    14. private static final int
    15.    
    16. int progressValue = 0; //保存进度条目前的进度值,当达到最大值时隐藏ProgressDialog
    17.  //引用的ProgressDialog对象
    18.     Handler progressHandler;  
    19.    
    20.     @Override  
    21. protected void
    22.         super.onCreate(savedInstanceState);  
    23.    
    24.         setContentView(R.layout.dialog3);  
    25.    
    26. new
    27.    
    28. public void
    29.    
    30. if(progressValue == 100){  
    31.                     mProgressDialog.dismiss();  
    32. else{  
    33. //设置进度条的值加1
    34.                     progressValue ++;  
    35.                     mProgressDialog.incrementProgressBy(1);  
    36. //如果进度条还没结束则100ms后进度条加1,循环调用每100ms就将进度条加1
    37.                     progressHandler.sendEmptyMessageDelayed(0, 100);  
    38.                 }  
    39.    
    40.             };  
    41.    
    42.         };  
    43.    
    44.     }  
    45.    
    46. public void
    47.    
    48. this,   
    49. "正在加载...", //标题
    50. "系统正在处理您的请求",  //内容
    51. true,  //是否不可确定值
    52. true); // 是否可取消
    53.     }  
    54.    
    55.     @Override  
    56. protected Dialog onCreateDialog(int
    57.    
    58. switch(id){  
    59.    
    60. case
    61. new ProgressDialog(this);  
    62. "进度条");   //设置标题
    63. "正在处理请稍后..."); //设置body信息
    64. //进度条最大值是100
    65. //设置进度条样式是 横向的
    66.    
    67. return
    68.    
    69.         }  
    70.    
    71. return
    72.     }  
    73.    
    74. public void
    75.    
    76.         showDialog(PROGRESS_DIALOG);  
    77.         progressValue = 0;  
    78.         mProgressDialog.setProgress(0);  
    79.         progressHandler.sendEmptyMessage(0);  
    80.    
    81.     }  
    82.    
    83. }



    代码运行效果如下:

    用户可以看到在走动的进度条,当进度条达到100时ProgressDialog就自动消失。这边一个难点就是Handler的用法,这个以后会再仔细介绍,现在先了解Handler就是可以将代码放到UI线程去执行即可。