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 小部件。