7.6 进度栏
进度栏(Progress Bar)可以反馈出后台任务是否正在处理或处理的进度,从而消除用户的心理等待时间。
在Android中,进度栏是android.widget.ProgressBar类,类图如图7-23所示,从图中可见android.widget.ProgressBar直接继承了android.view.View类。
图7-23 ProgressBar类图
7.6.1 进度栏相关属性和方法
进度栏有很多属性。下面是常用的几个属性:
❏ android:max。设置进度最大值。
❏ android:progress。设置当前进度。
❏ android:secondaryProgress。第二层进度栏进度。
❏ android:indeterminate。设置不确定模式进度栏,true为不确定模式。进度栏(ProgressBar)类中的常用方法如下:
❏ getMax()。返回进度最大值。
❏ getProgress()。返回进度值。
❏ getSecondaryProgress()。返回第二层进度栏进度值。
❏ incrementProgressBy(int diff)。设置增加进度。
❏ isIndeterminate()。判断是否为不确定模式。
❏ setIndeterminate(boolean indeterminate)。设置为不确定模式。
说明 什么是不确定模式(indeterminate)?一个任务的进度可以分为两种:可确定进度和不可确定进度。可确定进度是通过计算能够知道当前任务的进展情况,可以给用户一个完成的进度比例,还可以估算任务结束的时间。例如,估算Windows的安装进度,会显示安装了百分之几,还有多长时间完成。可确定进度模式能够给用户很好的体验;不可确定进度,是一些无法计算进展情况的任务,这些任务不知何时结束,但可以知道任务是进行还是停止。
Android系统提供了多种进度栏样式。其中一些与系统主题无关,如图7-24(a)、图7-24(d)、图7-24(f)所示;还有一些与系统主题有关,如图7-24(b)、图7-24(c)、图7-24(e)所示。下面是系统主题无关的6种样式:
图7-24 进度栏样式
❏ Widget.ProgressBar.Horizontal。水平条状进度栏。
❏ Widget.ProgressBar.Small。小圆形进度栏。
❏ Widget.ProgressBar.Large。大圆形进度栏。
❏ Widget.ProgressBar.Inverse。圆形进度栏。
❏ Widget.ProgressBar.Small.Inverse。小圆形进度栏。
❏ Widget.ProgressBar.Large.Inverse。大圆形进度栏。
在XML中,可以通过style="@android:style/ 进度栏样式 "进行设置,代码如下:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"/>
另外,还有与系统主题有关的8种样式:
❏ progressBarStyleHorizontal。水平条状进度栏。
❏ progressBarStyleSmall。小圆形进度栏。
❏ progressBarStyle。圆形进度栏。
❏ progressBarStyleLarge。大圆形进度栏。
❏ progressBarStyleSmallInverse。小圆形进度栏。
❏ progressBarStyleInverse。圆形进度栏。
❏ progressBarStyleLargeInverse。大圆形进度栏。
❏ progressBarStyleSmallTitle。标题栏中进度栏。
在XML中,可以通过style="? android:attr/ 进度栏样式 "进行设置,代码如下:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="? android:attr/progressBarStyleSmall"/>
注意 前文style属性中带有Inverse和不带有Inverse的区别;当进度栏控件所在的背景颜色为白色时,需要使用带有Inverse的样式。它们的区别不是旋转方向相反。
7.6.2 实例1:水平条状进度栏
水平条状进度是样式设置为Horizontal进度栏,条状进度栏非常适合可确定进度(indeterminate = true)的情况,但也可展示不可确定进度(indeterminate = false)的情况。
下面通过实例了解它们的使用情况。实例如图7-25所示,单击-和+按钮可改变进度,条状进度还可以有双层进度栏样式。
布局文件activity_main.xml代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent" android:orientation="vertical"> … <ProgressBar android:id="@+id/progress_horizontal01" android:layout_width="200dip" android:layout_height="wrap_content" style="@android:style/Widget.ProgressBar.Horizontal" ① android:max="100" ② android:progress="50"/> ③ <!--包含按钮栏--> <include android:id="@+id/button_bar1"layout="@layout/button_bar"/> … <ProgressBar android:id="@+id/progress_horizontal02" style="? android:attr/progressBarStyleHorizontal" ④ android:layout_width="200dip" android:layout_height="wrap_content" android:max="100" ⑤ android:progress="50" ⑥ android:secondaryProgress="75"/> ⑦ … <!--包含按钮栏--> <include android:id="@+id/button_bar2" layout="@layout/button_bar"/> … <!--包含按钮栏--> <include android:id="@+id/button_bar3" layout="@layout/button_bar"/> … <ProgressBar android:id="@+id/progress_horizontal03" style="? android:attr/progressBarStyleHorizontal" ⑧ android:layout_width="200dip" android:layout_height="wrap_content" android:indeterminate="true"/> ⑨ </LinearLayout>
图7-25 条状进度栏实例
上述代码第①行是设置系统主题无关的水平条状进度栏。而代码第④行和第⑧行是设置系统主题相关的水平条状进度栏。
由于id为progress_horizontal01和progress_horizon-tal02的进度栏都是可确定进度的,因此需要知道设定最大值属性android:max,见代码第②行和第⑤行;当前进度an-droid:progress属性见代码第③行和第⑥行。另外,progress_horizontal02的进度栏有两层进度栏,需要设定android:sec-ondaryProgress属性,见代码第⑦行。
id为progress_horizontal03的进度栏是不可确定进度的,需要android:indeterminate属性设置为true,见代码第⑨行。而android:max、android:progress和android:second-aryProgress这些属性对于它没有意义,不需要设定。
说明 布局文件activity_main.xml中使用include标签的原因是界面中有三组-和+按钮,形式上完全一样,功能类似。因此将-和+两个按钮在另外一个布局button_bar.xml中声明。然后,在三个不同的地方通过include标签载入。这样,减少维护-和+两个按钮布局的工作量。
声明-和+两个按钮的布局文件button_bar.xml的代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/decrease" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/progressbar_1_minus"/> <Button android:id="@+id/increase" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/progressbar_1_plus"/> </LinearLayout>
MainActivity.java代码如下:
public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); … final ProgressBar progressHorizontal02 =(ProgressBar) findViewById(R.id.progress_ horizontal02); //获取被包含按钮栏button_bar2 LinearLayout buttonBar2 =(LinearLayout) findViewById(R.id.button_bar2); ① Button bar2IncreaseButton=(Button) buttonBar2.findViewById(R.id.increase); ② bar2IncreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementProgressBy(1); ③ } }); Button bar2DecreaseButton=(Button) buttonBar2.findViewById(R.id.decrease); ④ bar2DecreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementProgressBy(-1); ⑤ } }); //获取被包含按钮栏button_bar3 LinearLayout buttonBar3 =(LinearLayout) findViewById(R.id.button_bar3); Button bar3IncreaseButton=(Button) buttonBar3.findViewById(R.id.increase); ⑥ bar3IncreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementSecondaryProgressBy(1); ⑦ } }); Button bar3DecreaseButton=(Button) buttonBar3.findViewById(R.id.decrease); ⑧ bar3DecreaseButton.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ progressHorizontal02.incrementSecondaryProgressBy(-1); ⑨ } }); } }
上述代码第③行和第⑤行是通过进度栏的incrementProgressBy方法增加和减少第一层进度栏的进度。代码第⑦行和第⑨行是通过进度栏的incrementSecondaryProgressBy方法增加和减少第二层进度栏的进度。
说明 在布局文件activity_main.xml中加载的button_bar.xml布局文件中声明了-和+两个按钮,它们的id是decrease和increase,如何获得这些按钮对象?解决办法是先通过MainActivity的findViewById方法,获得这些按钮所在的父视图(LinearLayout)对象,然后通过调父视图对象的findViewById方法获得按钮对象。例如,上述代码第①行findViewById(R.id.button_bar2)是获得父视图对象,参数id是在布局文件activity_main.xml的include android:id="@+id/button_bar2"layout="@layout/button_bar"/ 代码中声明的,代码第②行是调用父视图对象buttonBar2的findViewById获得+按钮。代码第④行是获得buttonBar2中-按钮,代码第⑥行是获得buttonBar3中的+按钮。
7.6.3 实例2:圆形进度栏
圆形进度栏一般应用在不可确定进度的任务,不需要设置android:max、android:progress和android:secondaryProgress等属性。
下面通过实例了解它们的使用情况。实例如图7-26所示,屏幕中有两个界面圆形进度栏和一个ToggleButton,通过单击ToggleButton可以隐藏或显示进度栏。
图7-26 圆形进度栏实例
布局文件activity_main.xml代码如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"android:layout_height="match_parent" android:orientation="vertical"> <ProgressBar android:id="@+id/progressBar1" style="? android:attr/progressBarStyleLarge" ① android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ProgressBar android:id="@+id/progressBar2" style="@android:style/Widget.ProgressBar.Small" ② android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ToggleButton ③ android:id="@+id/toggleButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOff="隐藏" ④ android:textOn="显示"/> ⑤ </LinearLayout>
上述布局文件声明了两个进度栏,代码第①行是设置progressBar1进度栏样式中与系统主题有关的大圆形进度栏,代码第②行设置progressBar2进度栏样式中与系统主题无关的小圆形进度栏。
代码第③行声明了ToggleButton来实现进度栏隐藏和显示两种状态的切换。由于ToggleButton默认两种状态的标题是OFF或NO,手机设置为中文显示是“关闭”或“开启”,但是本例中需要显示“隐藏”或“显示”。
MainActivity.java代码如下:
public class MainActivity extends AppCompatActivity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ProgressBar progressBar1 =(ProgressBar) findViewById(R.id.progressBar1); final ProgressBar progressBar2 =(ProgressBar) findViewById(R.id.progressBar2); final ToggleButton button=(ToggleButton) findViewById(R.id.toggleButton); button.setOnClickListener(new Button.OnClickListener(){ public void onClick(View v){ boolean checked = button.isChecked(); if(checked){ progressBar1.setVisibility(ProgressBar.GONE); ① progressBar2.setVisibility(ProgressBar.INVISIBLE); ② }else{ progressBar1.setVisibility(ProgressBar.VISIBLE); ③ progressBar2.setVisibility(ProgressBar.VISIBLE); ④ } } }); } }
上述代码第①、②、③、④行都是通过setVisibility方法设置进度栏的隐藏或显示,setVisibility方法中的参数有三个:
❏ ProgressBar.VISIBLE。显示,见代码第③和④行。
❏ ProgressBar.INVISIBLE。隐藏,占有空间。例如,上述代码progressBar2设置ProgressBar.INVISIBLE,结果如图7-26(b)所示,按钮顶部的空白是隐藏的progressBar2。
❏ ProgressBar.GONE。隐藏,不占有空间。例如,上述代码progressBar1设置ProgressBar.GONE,结果如图7-26(b)所示,按钮位置向上一段距离,事实上这个距离是progressBar1的高度。