android 自定义下载进度条

继承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);
	}


转载于:https://my.oschina.net/blackylin/blog/123589

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值