Android ProgressBar 小部件
最后修改于 2012 年 11 月 29 日
在本章 Android 开发教程中,我们将介绍 ProgressBar
小部件。ProgressBar
是一个直观显示某个任务进度的小部件。该小部件有两种基本模式:圆形进度条和水平进度条。
我们将通过两个示例来演示它们。
ProgressBar I
我们有一个水平 ProgressBar
小部件和一个 TextView
小部件,用于显示任务完成的百分比。清单文件保持不变。
<?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" > <ProgressBar android:id="@+id/pbId" android:layout_width="fill_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:layout_margin="10dp" /> <TextView android:id="@+id/tvId" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dp" /> </LinearLayout>
在 main.xml
布局文件中,我们有一个 ProgressBar
和一个 TextView
。style="?android:attr/progressBarStyleHorizontal"
样式使 ProgressBar
成为水平样式。ProgressBar
的默认模式是圆形模式。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">ProgBar</string> </resources>
字符串资源文件。
package com.zetcode.progbar2; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ProgressBar; import android.widget.TextView; import android.util.Log; public class MainActivity extends Activity { ProgressBar pb; TextView tv; int prg = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); pb = (ProgressBar) findViewById(R.id.pbId); tv = (TextView) findViewById(R.id.tvId); new Thread(myThread).start(); } private Runnable myThread = new Runnable() { @Override public void run() { while (prg < 100) { try { hnd.sendMessage(hnd.obtainMessage()); Thread.sleep(100); } catch(InterruptedException e) { Log.e("ERROR", "Thread was Interrupted"); } } runOnUiThread(new Runnable() { public void run() { tv.setText("Finished"); } }); } Handler hnd = new Handler() { @Override public void handleMessage(Message msg) { prg++; pb.setProgress(prg); String perc = String.valueOf(prg).toString(); tv.setText(perc+"% completed"); } }; }; }
我们创建一个线程来控制 ProgressBar
的进度。
new Thread(myThread).start();
启动了一个新线程。在 Android 中,耗时任务应该在线程中执行,以防止应用程序看起来无响应。线程通过从其 main()
方法返回或通过异常来结束。
@Override public void run() { while (prg < 100) { try { hnd.sendMessage(hnd.obtainMessage()); Thread.sleep(100); } catch(InterruptedException e) { Log.e("ERROR", "Thread was Interrupted"); } } runOnUiThread(new Runnable() { public void run() { tv.setText("Finished"); } }); }
线程中的代码放在 run()
方法中。我们将通过调用 Thread.sleep()
方法来模拟耗时任务。这迫使我们处理 InterruptedException
。Android 应用程序运行在单线程模型中。主活动的所有组件都在主线程中创建。这些组件不能在其他线程中进行操作。为了解决这个问题,我们使用 Handler
对象或调用 runOnUiThread()
方法。
runOnUiThread(new Runnable() { public void run() { tv.setText("Finished"); } });
只有创建视图层次结构的原始线程才能触及其视图。在这里,我们正在修改 TextView
小部件。因此,我们将代码放入 runOnUiThread()
方法中,该方法在创建小部件的主 UI 线程中执行代码。
Handler hnd = new Handler() { @Override public void handleMessage(Message msg) { prg++; pb.setProgress(prg); String perc = String.valueOf(prg).toString(); tv.setText(perc+"% completed"); } };
从另一个线程操作小部件的另一种方法是使用 Handler
对象。它用于将操作排队,以便在与自身不同的线程上执行。我们更新进度条并设置已完成任务的百分比到文本视图。

ProgressBar II
在第二个示例中,我们展示了 ProgressBar
在圆形模式下的用法。清单文件无需修改。
<?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" > <ProgressBar android:id="@+id/pbId" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/tvId" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/msg" /> </LinearLayout>
在 main.xml
文件中,我们有一个 ProgressBar
和一个 TextView
。ProgressBar
具有默认样式,即圆形样式。这等同于使用了 style="?android:attr/progressBarStyle"
属性。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">CirProgBar</string> <string name="msg">Please wait...</string> </resources>
我们在 strings.xml
文件中有两个字符串资源。
package com.zetcode.progbar; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ProgressBar; import android.widget.TextView; import android.view.View; import android.util.Log; public class MainActivity extends Activity { ProgressBar pb; TextView tv; int prg = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); pb = (ProgressBar) findViewById(R.id.pbId); tv = (TextView) findViewById(R.id.tvId); new Thread(myThread).start(); } private Runnable myThread = new Runnable() { @Override public void run() { while (prg < 100) { try { hnd.sendMessage(hnd.obtainMessage()); Thread.sleep(100); } catch(InterruptedException e) { Log.e("ERROR", "Thread was Interrupted"); } } runOnUiThread(new Runnable() { public void run() { tv.setText("Finished"); pb.setVisibility(View.GONE); } }); } Handler hnd = new Handler() { @Override public void handleMessage(Message msg) { prg++; pb.setProgress(prg); } }; }; }
代码与第一个示例类似,但有一些修改。
runOnUiThread(new Runnable() { public void run() { tv.setText("Finished"); pb.setVisibility(View.GONE); } });
任务完成后,我们使用 setVisibility()
方法隐藏 ProgressBar
。圆本身是无限动画,因此在任务完成后,我们需要隐藏该小部件。

在本章 Android 开发教程中,我们提到了 ProgressBar
小部件。