继承view实现下载进度条,大家可以参考修改出更好的实现方式,欢迎指正,下面是源码和截图:
1.测试代码:
DownloadProgressBar dpb;
synchronized void updateUIData(float rate){
dpb.setProgress(rate);
}
void test(){
dpb=new DownloadProgressBar(this);
dpb.setWH(100, 4);
new Thread(new Runnable() {
int rate = 0;
@Override
public void run() {
while(true){
try {
if(rate>100){
break;
}
myHandler.post(new Runnable() { //用handler在线程中刷新数据
@Override
public void run() {
Log.i(TAG,"####@@@@rate:"+rate);
if(rate == 2){
rate+=2;
}else if(rate ==10){
rate+=10;
}else if(rate ==20){
rate+=10;
}else if(rate ==50){
rate+=20;
}else{
rate++;
}
updateUIData(rate);
}
});
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
2.进度条源码
1>首先设置进度条的宽和高,代码里设定宽度应该为100的整数倍,不然进度条显示的数据并不准确。
2>文件下载的话,可以用上诉例子替换成不停的读以下载的文件大小,然后根据文件总大小得到相对比例,调用updateUIData(rate)刷新ui
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class DownloadProgressBar extends View{
private static final String TAG="DownloadProgressBar";
Context cxt;
public DownloadProgressBar(Context context) {
this(context, null);
}
public DownloadProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
cxt = context;
this.setBackgroundResource(R.drawable.jdt02);
bitmap =BitmapFactory.decodeResource(cxt.getResources(), R.drawable.jdt03);
mCanvas = new Canvas();
mpaint = new Paint();
}
private int w,h;
/**
* 设置进度条的宽高
*
* @param w
* 宽
* @param h
* 高
* */
public void setWH(int w,int h){
this.w= w;
this.h=h;
}
float rate ;
float rate_t;
/**
* 设置进度比例
*
* @param r
* 当前占的比例值
* */
public void setProgress(float r){
this.rate_t = w/100*r; //(w/100)这里假定以w为100的整数倍
invalidate((int)rate,0,w,h);
//invalidate();
}
public void clearProgress(){
rate = 0;
}
Canvas mCanvas;
Paint mpaint;
Bitmap bitmap; //一个像素宽的绿色小图片
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
while(rate<=rate_t){
for(int i=0;i<w/100;i++){
Log.i(TAG,"rate:"+rate+",rate_t:"+rate_t);
canvas.drawBitmap(bitmap, rate++, 0, null);
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(w, h);
}
}
3.进度条改进版源码
前面代码出现的问题:
1.每次刷新因为只刷新部分区域,导致按键事件的时候,因为会重新刷新ui,而默认是invalidate()全刷新,导致前面部分的进度没有了
而如果用全部刷新来画每个像素的话,是非常消耗系统资源的,这里简单算下:
a>如果这里用的图片像素宽度是1px的话,而进度条的宽度为400,则
每次ondraw都从0开始画,drawCount = 1+2+3+4+...+400=(1+400)*400/2=80200;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
public class DownloadProgressBar extends View{
private static final String TAG="DownloadProgressBar";
Context cxt;
public DownloadProgressBar(Context context) {
this(context, null);
}
public DownloadProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
cxt = context;
this.setBackgroundResource(R.drawable.bar_01);
if(bitmap!=null){
bitmap.recycle();
}
bitmap =BitmapFactory.decodeResource(cxt.getResources(), R.drawable.bar_04); //和背景大小一致的全绿色图片
mCanvas = new Canvas();
mpaint = new Paint();
}
private int w,h;
/**
* 设置进度条的宽高
*
* @param w
* 宽
* @param h
* 高
* */
public void setWH(int w,int h){
this.w= w;
this.h=h;
}
float rate = 0;
float rate_t;
/**
* 设置进度比例
*
* @param r
* 当前占的比例值
* */
public void setProgress(float r){
if(r>99){
this.setBackgroundResource(R.drawable.bar_04);
return;
}
this.rate_t = w/100*r;
//Log.i(TAG,"setProgress:rate="+rate+",rate_t:"+rate_t);
//invalidate((int)rate,0,w,h);
invalidate();
}
public void clearProgress(){
rate = 0;
}
Canvas mCanvas;
Paint mpaint;
Bitmap bitmap;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// while(rate<=rate_t){
// for(int i=0;i<w/100;i++){
// //Log.i(TAG,"rate:"+rate+",rate_t:"+rate_t);
// canvas.drawBitmap(bitmap, rate++, 0, null);
// }
// }
clipDraw(canvas);
}
void clipDraw(Canvas canvas){ //用剪切区域来显示进度条,减少画单个像素的次数
canvas.save();
canvas.clipRect(0,0,rate_t, h);
canvas.drawBitmap(bitmap,0, 0, null);
canvas.restore();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(w, h);
}