前一段时间,由于项目需要研究了下progressbar,发现这个小东西还真是不简单。在这个小控件的显示效果上,花费的时间远大于预估的工作量。话说程序员一直是这样,预估的工作量远少于实际。。。
先说明一下,这里主要是针对水平进度条进行说明的,关于圆形进度条或者其他进度条可以依此类推。android系统默认的进度条是圆形的,用到水平进度条一般都会加上这样一个属性:"@android:style/Widget.ProgressBar.Horizontal"。笔者所发现进度条特殊的地方都是从这里开始的。建议大家看这篇文章的时候最好关联源码或者关联SDK,看到这个属性的内部定义。
对于textview这类控件,直接使用如下两个属性一般就可以达到GUI要求的宽度和高度,
android:layout_width="wrap_content" android:layout_height="wrap_content"
而对于progressbar,GUI除了会对这个控件本身的大小做一定要求,更多的会对这个控件里面的进度条大小有要求。这里就到了第一个特殊点:progressbar相对于textview这类控件来说需要控制两个地方的大小:1.这个控件本身的大小,也就是实际占据的位置;2.这个控件里面用来显示进度的那块大小。
我们如果仅仅设置上面两个属性,会发现里面的进度条仅仅是随着控件本身的增大而同比例增大,也就达不到GUI要求的效果。笔者在阅读Widget.ProgressBar.Horizontal属性源码时候发现,其内部定义是这样的:
<style name="Widget.ProgressBar.Horizontal"> <item name="android:indeterminateOnly">false</item> <item name="android:progressDrawable">@android:drawable/progress_horizontal</item> <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item> <item name="android:minHeight">20dip</item> <item name="android:maxHeight">20dip</item> <item name="android:mirrorForRtl">true</item> </style>
有没有注意到,这里还有minHeight,maxHeight这两个属性,尝试修改了一下达到效果。好了到这里设置进度条进度大小的属性就说完了。一个GUI的效果图会给出控件多大,里面进度和和控件边沿之间的间隙是多大。我们可以直接在layout_width这种属性中设置控件大小,在android:maxHeight里面设置进度的大小。
GUI除了会要求设定进度的大小,还会要求改变进度本身的大小比如图片或者角度。是的,GUI什么的不会轻易放过程序员的。有没有注意到,上面的源码有个这样的定义
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
猜测突破口就是这里,查看了一下google的定义貌似很复杂的样子。原来就里面的那个进度,其背景颜色还要分为:1.单独的背景颜色;2.进度的背景颜色;3.第二进度的背景颜色。而且所有的颜色值,转角大小都是用代码给写出来的,着实是复杂。这里直接就告诉大家吧,通过我们的研究以及其他项目组充满血泪的经验总结,在这里直接用GUI画的图是最方便的。一般自定义的进度条背景色,最终实现出来的代码都是下面的格式
<?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/******" /> <item android:id="@android:id/progress" android:drawable="@drawable/*******" /> </layer-list>
看到这里是不是感觉人生充满了欢乐。
最后在给进度条加上百分比,原以为android会提供这个属性,查了半天真的木有。最后我们想到了两种实现方法,貌似都还不错。先说说第一个方法的思路,继承progress控件通过控件画图回调方法onDraw(Canvas),在画出一个百分比出来。关于第二个方法,也是新定一个控件,用framelayout封装一个progressbar,一个textview。就个人来说比较倾向第一种方法,这个貌似能逐步加深对android一些理解,对于第二个方法呢,在各个平台上具有通用性,也不错。直接给出第一个方法的实现:
package com.example.android.apis; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.text.TextPaint; import android.widget.ProgressBar; public class PercentProgressbar extends ProgressBar { String text; Paint mTextPaint; public PercentProgressbar(Context context) { super(context); initText(); } @Override public synchronized void setProgress(int progress) { super.setProgress(progress); setText(progress); } @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); Rect rect = new Rect(); this.mTextPaint.getTextBounds(this.text, 0, this.text.length(), rect); int x = (getWidth() / 2) - rect.centerX(); int y = (getHeight() / 2) - rect.centerY(); canvas.drawText(this.text, x, y, this.mTextPaint); } private void initText() { this.mTextPaint = new TextPaint(); this.mTextPaint.setColor(Color.WHITE); //还可以设置字体的其他属性 } private void setText(int progress){ int i = (progress * 100)/this.getMax(); this.text = String.valueOf(i) + "%"; } }
这里也参考了一下网上的实现,不过发现网络上大多数使用的画笔都是paint,建议大家还是使用textpaint。否则进度条里面的文字和界面其他地方的文字总是有些不一样的地方,GUI不会放过你们的。。。在强调一点,进度条里面的百分比,是不应该随着系统字体大小变化而变化的,所以设置字体的时候请记得使用DP做为单位。在上面的第二个方法里面直接在textview控件里面设置字体大小就可以了,那么在第一种方法里面应该怎么设置字体大小呢,这里就留给大家思考把。(本帖阅读量达到2000,公布方法)
总结一下,文章讲解的是progressbar,不过并木有介绍怎么使用progressbar显示进度什么的。类似这种最基础的知识,可以看下google的APIDemo。这里讲解了progressbar设置内部进度大小,设置内部进度图片,怎么显示百分比。相信关于progressbar最常见的,但是Demo里面没有提到的,都在这里了。
progressbar用法:进度画面大小,进度画面背景,进度百分比,布布扣,bubuko.com