- Android开发权威指南(第二版)
- 李宁编著
- 530字
- 2024-12-21 14:46:43
14.1 进度条控件
任务或工作的进度是软件中经常要展现给用户的信息,这些信息的载体总是离不开进度条。在Android SDK中提供了一个ProgressBar控件,该控件可以向用户展示当前任务的进度。除此之外,SeekBar和RatingBar控件从本质上讲也应属于进度条,只不过这两个控件对进度条的功能做了进一步改进,也可以将它们看作是进度条的变种。本节将详细介绍这3个控件的用法。
14.1.1 ProgressBar(进度条控件)
源代码目录:src/ch14/ProgressBar
ProgressBar控件在默认情况下是圆形的进度条,可通过style属性将圆形进度条设为大、中、小3种形式,代码如下:
源代码文件:src/ch14/ProgressBar/res/layout/main.xml
<!-- 圆形进度条(小) -->
<ProgressBar android:layout_width="wrap_content"
android:layout_height="wrap_content" style="?android:attr/progressBarStyleSmallTitle" />
<!-- 圆形进度条(中) -->
<ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" />
<!-- 圆形进度条(大) -->
<ProgressBar android:layout_width="wrap_content"
android:layout_height="wrap_content" style="?android:attr/progressBarStyleLarge" />
ProgressBar控件在默认情况下显示的是中型的圆形进度条,因此,要想显示中型的圆形进度条,并不需要设置style属性。
除了圆形进度条外,ProgressBar控件还支持水平进度条,代码如下:
源代码文件:src/ch14/ProgressBar/res/layout/main.xml
<ProgressBar android:id="@+id/progressBarHorizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal" android:max="100"
android:progress="30" android:secondaryProgress="60" android:layout_marginTop=
"20dp" />
ProgressBar控件的水平进度条支持两级进度,分别使用android:progress和android:secondary Progress属性设置,进度条的总刻度使用android:max属性设置。在本例中android:max属性的值为100,android:progress和android:secondaryProgress属性的值分别是30和60。也就是说,第1级进度和第2级进度分别显示在进度条总长度30%和60%的位置上。
android:max属性的值不一定是100,该值可以是任意一个正整数,例如,360。一般来说,android:progress和android:secondaryProgress属性的值要小于等于android:max属性的值。当然,如果这两个属性的值大于android:max属性的值,则会显示100%的状态。如果这两个属性的值小于0,则会显示0%的状态。如果只想使用一级进度,可以只设置android:progress或android:secondaryProgress属性。
在代码中设置水平进度条的两级进度需要使用ProgressBar类的setProgress和setSecondary Progress方法,代码如下:
源代码文件:src/ch14/ProgressBar/src/mobile/android/progressbar/Main.java
ProgressBar progressBarHorizontal = (ProgressBar) findViewById(R.id.progressBarHorizontal);
// 设置第1级进度
progressBarHorizontal.setProgress((int) (progressBarHorizontal.getProgress()* 1.2));
// 设置第2级进度
progressBarHorizontal.setSecondaryProgress((int) (progressBarHorizontal.getSecondaryProgress()* 1.2));
Android系统还支持将水平和圆形进度条放在窗口的标题栏上。例如,可以在onCreate方法中使用如下代码将圆形进度条放在窗口的标题栏上。
源代码文件:src/ch14/ProgressBar/src/mobile/android/progressbar/Main.java
// 必须在调用setContentView方法之前设置窗口的Feature
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
setProgressBarIndeterminateVisibility(true); // 显示圆形进度条
如果要将水平进度条放在标题栏上,可以在onCreate方法中使用如下代码:
源代码文件:src/ch14/ProgressBar/src/mobile/android/progressbar/Main.java
requestWindowFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.main);
setProgressBarVisibility(true); // 显示水平进度条
setProgress(3500); // 设置水平进度条的当前进度
将进度条放在窗口标题栏上时应了解如下几点。
requestWindowFeature方法应在调用setContentView方法之前调用,否则系统会抛出异常。
setProgressBarIndeterminateVisibility、setProgressBarVisibility和setProgress方法要在调用setContentView方法之后调用,否则这些方法无效。
放在标题栏上的水平进度条不能设置进度条的最大刻度,这是因为系统已经将最大刻度值设为10000,也就是说,用setProgress方法设置的进度应在0~10000之间。例如,本例中设为3500,进度会显示在进度条总长的35%的位置上。
本例的显示效果如图14-1所示。单击“增加进度”和“减小进度”按钮后,最后一个进度条会以当前进度20%的速度递增和递减。
▲图14-1 水平和圆形进度条
14.1.2 SeekBar(拖动条控件)
源代码目录:src/ch14/SeekBar
SeekBar控件可以通过拖动滑杆改变当前的值,可以利用SeekBar设置具有一定范围的变量值。例如,在13.4.3小节的例子中使用了SeekBar控件来控制图像的旋转角度。那么在这个例子中SeekBar设置的变量就是图像旋转的角度(0至360)。下面我们再来回顾一下SeekBar控件的基本用法,并介绍一下相关的事件。
SeekBar控件的使用方法与ProgressBar控件类似,代码如下:
源代码文件:src/ch14/SeekBar/res/layout/main.xml
<SeekBar android:id="@+id/seekbar" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:max="100" android:progress="30" />
<SeekBar android:id="@+id/seekbar2" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:max="100"
android:progress="30" android:secondaryProgress="60"/>
虽然SeekBar是ProgressBar的子类,但一般SeekBar控件并不需要设置第2级进度(设置android:secondaryProgress属性)。如果设置了android:secondaryProgress属性,系统仍然会显示第2级的进度,不过并不会随着滑杆移动而递增或递减。
与SeekBar控件滑动相关的事件接口是OnSeekBarChangeListener,该接口定义了如下3个事件方法:
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser);
public void onStartTrackingTouch(SeekBar seekBar);
public void onStopTrackingTouch(SeekBar seekBar)。
当按住滑杆后,系统会调用onStartTrackingTouch方法,在滑杆滑动时,会调用onProgressChanged方法,松开滑杆后,会调用onStopTracking方法。
在本节的例子中有两个SeekBar控件,第1个SeekBar控件只设置了第1级进度,第2个SeekBar控件同时设置了第1级和第2级进度。当这两个SeekBar控件的滑杆滑动时,在onProgressChanged方法中分别处理相应SeekBar控件的滑动事件,实现代码如下:
源代码文件:src/ch14/SeekBar/src/mobile/android/seekbar/Main.java
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
{
// 第1个SeekBar控件
if (seekBar.getId() == R.id.seekbar1)
textView2.setText("seekbar1的当前位置:" + progress);
else // 第2个SeekBar控件
textView2.setText("seekbar2的当前位置:" + progress);
}
运行本例后,滑动两个SeekBar控件中的滑杆,显示效果如图14-2所示。
▲图14-2 SeekBar 控件
14.1.3 设置ProgressBar和SeekBar的颜色及背景图
源代码目录:src/ch14/ColorBar
14.1.1 小节和14.2.2小节介绍的ProgressBar和SeekBar控件的进度条都是黄色的,但为了设计出更酷的界面,有时需要改变进度条的颜色,或为进度条添加背景图。而ProgressBar和SeekBar类均未提供直接修改进度条颜色或背景图的方法或属性。不过这个问题可以通过<ProgressBar>、<SeekBar>标签的android:progressDrawable属性来解决。
一个完整的ProgressBar或SeekBar控件由如下3部分组成:
第1级进度条;
第2级进度条;
背景,也就是进度条未经过的地方。
因此,这两个控件的颜色也应该由3部分组成:第1级进度条颜色、第2级进度条颜色和背景颜色。在前面提到过,可以通过android:progressDrawable属性来设置ProgressBar和SeekBar的这3部分颜色。那么只使用一个属性如何设置3个颜色值呢?
在前面的章节中曾多次使用过res/drawable目录中的图像资源,知道这个目录保存的是图像资源(png、gif、jpg等),但该资源目录中的图像资源并不一定是图像文件,还可以是xml文件。当然,在res/drawable目录中的xml文件与res/values或其他资源目录中的xml文件不一样,res/drawable目录中的xml文件中实际上也定义了若干个图像资源,以及图像资源的各种状态。本节的例子通过res/drawable目录中的xml文件定义一组图像资源,并为每一个图像资源指定一个ID,通过这些ID设置ProgressBar和SeekBar控件中的背景色(图像)、第1级进度条颜色(图像)、第2级进度条颜色(图像)。
设置上述ProgressBar和SeekBar控件的3种颜色的步骤如下。
第1步:确定这3种颜色后,使用绘图工具建立3个图像文件,并分别用3种不同的颜色填充这3个图像。图像的大小可任意选择。在本例中,progress.png文件表示第1级进度条颜色;secondary.png表示第2级进度条颜色;bg.png表示背景颜色。
第2步:在res/drawable目录下建立一个barcolor1.xml文件,并输入如下代码:
源代码文件:src/ch14/ColorBar/res/drawable/barcolor1.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置背景色图像资源 -->
<item android:id="@android:id/background" android:drawable="@drawable/bg" />
<!-- 设置第2级进度条颜色图像资源 -->
<item android:id="@android:id/secondaryProgress" android:drawable="@drawable/
secondary" />
<!-- 设置第1级进度条颜色图像资源 -->
<item android:id="@android:id/progress" android:drawable="@drawable/progress" />
</layer-list>
第3步:在<ProgressBar>和<SeekBar>标签中使用android:progressDrawable属性指定barcolor1.xml文件的资源ID,代码如下:
源代码文件:src/ch14/ColorBar/res/layout/main.xml
<ProgressBar android:id="@+id/progressBarHorizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content"
style="?android:attr/progressBarStyleHorizontal"
android:max="100" android:progress="30" android:secondaryProgress="60"
android:progressDrawable="@drawable/barcolor1" />
<SeekBar android:layout_width="fill_parent"
android:layout_height="wrap_content" android:max="100"android:progress="30"
android:progressDrawable="@drawable/barcolor" />
在barcolor1.xml文件中设置了3个图像,其中<item>标签中的android:id属性指的是系统的3个ID资源,系统会根据这3个ID资源来设置相应的android:drawable属性。<item>的父标签是<layer-list>,这个标签负责管理若干个Drawable对象,其中<layer-list>必须是根节点。在程序中<layer-list>及<item>都会有对应的Drawable对象。例如,<layer-list>对应LayerDrawable对象,在barcolor1.xml文件中的<item>标签对应于BitmapDrawable对象。因此,我们可以使用下面的代码输出barcolor1.xml文件中的相应信息。
源代码文件:src/ch14/ColorBar/src/mobile/android/color/bar/Main.java
// 根据barcolor1.xml文件中的根节点(<layer-list>标签)来创建LayerDrawable对象
LayerDrawable layerDrawable = (LayerDrawable) getResources().getDrawable (R.drawable. barcolor1);
// 输出<layer-list>标签中子标签(<item>节点)数,本例应为3
Log.d("layerDrawable_child_count",String.valueOf(layerDrawable.getNumberOfLayers()));
// 输出第1个<item>标签中android:id属性值的十进制形式
Log.d("background_id", String.valueOf(layerDrawable.getId(0)));
// 输出第1个<item>标签对应的Drawable对象名(BitmapDrawable)
Log.d("background",String.valueOf(layerDrawable.getDrawable(0).getClass()));
// 输出第2个<item>标签对应的Drawable对象名(BitmapDrawable)
Log.d("secondaryProgress",String.valueOf(layerDrawsable.getDrawable(1).getClass()));
// 输出第3个<item>标签对应的Drawable对象名(BitmapDrawable)
Log.d("progress",String.valueOf(layerDrawable.getDrawable(2).getClass()));
上面代码中的layerDrawable.getDrawable方法实际上获得的就是<item>标签的android:drawable属性值指向的图像资源的BitmapDrawable对象。运行上面的代码,会在LogCat视图中输出如图14-3所示的信息。
▲图14-3 输出LayerDrawable及其子对象的相关信息
我们也可以设置部分ProgressBar和SeekBar的颜色,例如,下面的代码只设置了背景色和第1级进度条的颜色,并且第1级进度条的颜色使用的并不是纯色的图像,而是一个24×24的图像。如果图像不够宽,系统会自动以平铺方式显示该图像。
源代码文件:src/ch14/ColorBar/res/drawable/barface.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background" android:drawable="@drawable/bg" />
<item android:id="@android:id/progress" android:drawable="@drawable/face" />
</layer-list>
除了前面介绍的几种设置颜色的方法,还可以使用更高级的方式进行设置,甚至可以设置成渐变色。例如,barcolor2.xml将背景色设为垂直方向的渐变色(由红到黑),而且增加了控件两头的圆角半径。
源代码文件:src/ch14/ColorBar/res/drawable/barcolor2.xml
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="10dip" />
<gradient android:startColor="#FFFF0000"
android:centerColor="#FF880000" android:centerY="0.75"
android:endColor="#FF110000" android:angle="270" />
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="10dp" />
<gradient android:startColor="#FF00FF00"
android:centerColor="#FF00FF00" android:centerY="0.75"
android:endColor="#FF00FF00" android:angle="270" />
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<corners android:radius="10dp" />
<gradient android:startColor="#ffffd300"
android:centerColor="#ffffb600" android:centerY="0.75"
android:endColor="#ffffcb00" android:angle="270" />
</shape>
</clip>
</item>
</layer-list>
运行本例,会看到如图14-4所示的显示效果。
▲图14-4 设置ProgressBar和SeekBar 的颜色
14.1.4 RatingBar(评分控件)
源代码目录:src/ch14/Ratingar
在很多电子相册、网上书店、博客中都会有对照片、图书和文章进行评分的功能(很多评分系统都是满分为5分,分10个级,0~5,步长为0.5)。在Android SDK中也提供了RatingBar控件用来完成类似的工作。
RatingBar控件使用<RatingBar>标签进行配置。该标签有如下几个与评分相关的属性。
android:numStars:指定用于评分的五角星数,默认情况下根据布局的设置尽量横向填充。
android:rating:指定当前的分数。
android:stepSize:指定分数的增量单位(步长),默认是0.5。
下面的代码分别设置了不同的五角星数和步长。
源代码文件:src/ch14/RatingBar/res/layout/main.xml
<RatingBar android:id="@+id/ratingbar1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:numStars="3" android:rating="2" />
<RatingBar android:id="@+id/ratingbar2" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:numStars="5" android:stepSize="0.1" />
除此之外,还可以为RatingBar控件设置不同的风格,代码如下:
源代码文件:src/ch14/RatingBar/res/layout/main.xml
<!-- 设置小五角星风格 -->
<RatingBar android:id="@+id/smallRatingbar" style="?android:attr/ratingBarStyleSmall"
android:layout_marginLeft="5dip" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 设置指示五角星风格 -->
<RatingBar android:id="@+id/indicatorRatingbar" style="?android:attr/ratingBarStyle
Indicator"
android:layout_marginLeft="5dip" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:stepSize="0.1"/>
通过实现android.widget.RatingBar.OnRatingBarChangeListener接口可以监听RatingBar控件的动作。当RatingBar控件的分数变化后,系统会调用OnRatingBarChangeListener.onRatingChanged方法。可以在该方法中编写处理分数变化的代码,例如,更新小五角星风格和指示五角星风格的RatingBar控件的当前分数。
源代码文件:src/ch14/RatingBar/src/mobile/android/ratingbar/Main.java
public void onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser)
{
smallRatingBar.setRating(rating); // 更新小五角星风格的RatingBar控件的当前分数
indicatorRatingBar.setRating(rating); // 更新指示五角星风格的RatingBar控件的当前分数
if (ratingBar.getId() == R.id.ratingbar1)
textView.setText("ratingbar1的分数:" + rating);
else
textView.setText("ratingbar2的分数:" + rating);
}
运行本例,为前两个RatingBar控件评分后,后两个RatingBar控件也会更新成相应的分数,显示效果如图14-5所示。
▲图14-5 RatingBar 控件