1. 程式人生 > >Android百分比下載進度條

Android百分比下載進度條


        現在很多APP中都會整合下載功能,所以有一個方便好看又實用的進度條來展示下載進度很有必要,也能提高使用者體驗,在這裡我就把專案裡的下載進度條抽取出來分享給大家,話不多說,先看效果圖:


這個進度條是自定義的一個View,其中有一個自定義屬性就是百分比文字的大小(也可以把那兩條顯示顏色的進度條自定義屬性,這裡就沒有實現,在程式碼裡面寫的)。

先說說實現原理:

1:由於自定義了屬性,所以先獲取屬性的值。

2:繪製底色那條灰色的線。

3:根據傳入的資料計算當前百分比,然後繪製那條橘黃色的線。

4:再在橘黃色線後面把百分比的文字繪製出來就OK了。

現在來看看程式碼:

一:屬性設定attrs.xml檔案

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="downloadProgressBar">
        <attr name="dptextsize" format="dimension"/>
    </declare-styleable>
</resources>
其中dptextsize就是自定義屬性的名字


二:自定義view DownLoadProgressbar.java

package com.ywl5320.downloadprogressdemo.downloadview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;

import com.ywl5320.downloadprogressdemo.R;

/**
 * 下載進度條
 * 
 * @author ywl
 *
 */
public class DownLoadProgressbar extends View {

	private Paint paint = new Paint(); // 繪製背景灰色線條畫筆
	private Paint paintText = new Paint(); // 繪製下載進度畫筆
	private float offset = 0f; // 下載偏移量
	private float maxvalue = 0f; // 下載的總大小
	private float currentValue = 0f; // 下載了多少
	private Rect mBound = new Rect(); // 獲取百分比數字的長寬
	private String percentValue = "0%"; // 要顯示的現在百分比
	private float offsetRight = 0f; // 灰色線條距離右邊的距離
	private int textSize = 25; // 百分比的文字大小
	private float offsetTop = 18f; // 距離頂部的偏移量

	public DownLoadProgressbar(Context context) {
		this(context, null);
		// TODO Auto-generated constructor stub
	}

	public DownLoadProgressbar(Context context, AttributeSet attribute) {
		this(context, attribute, 0);
	}

	public DownLoadProgressbar(Context context, AttributeSet attrs,
			int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO Auto-generated constructor stub
		// 獲取自定義屬性,給textsize賦初始值
		TypedArray t = getContext().obtainStyledAttributes(attrs,
				R.styleable.downloadProgressBar);
		textSize = (int) t.getDimension(
				R.styleable.downloadProgressBar_dptextsize, 36);
		getTextWidth();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		// 繪製底色
		paint.setColor(getResources().getColor(R.color.no1_gray_light));
		paint.setStrokeWidth(1);
		canvas.drawLine(0, offsetTop, getWidth(), offsetTop, paint);
		// 繪製進度條顏色
		paint.setColor(getResources().getColor(R.color.no2_orange));
		paint.setStrokeWidth(2);
		canvas.drawLine(0, offsetTop, offset, offsetTop, paint);
		// 繪製白色區域及百分比
		paint.setColor(getResources().getColor(R.color.no3_white));
		paint.setStrokeWidth(1);
		paintText.setColor(getResources().getColor(R.color.no2_orange));
		paintText.setTextSize(textSize);
		paintText.setAntiAlias(true);
		paintText.getTextBounds(percentValue, 0, percentValue.length(), mBound);
		canvas.drawLine(offset, offsetTop, offset + mBound.width() + 4, offsetTop, paint);
		canvas.drawText(percentValue, offset, offsetTop + mBound.height() / 2 - 2, paintText);
	}

	/**
	 * 設定當前進度值
	 * 
	 * @param currentValue
	 */
	public void setCurrentValue(float currentValue) {
		this.currentValue = currentValue;
		int value = (int) (this.currentValue / maxvalue * 100);
		if (value < 100) {
			percentValue = value + "%";
		} else {
			percentValue = "100%";
		}
		initCurrentProgressBar();
		invalidate();
	}

	/**
	 * 設定最大值
	 * 
	 * @param maxValue
	 */
	public void setMaxValue(float maxValue) {
		this.maxvalue = maxValue;
	}

	/**
	 * 獲取當前進度條長度
	 * 
	 * @param maxValue
	 * @param currentValue
	 * @return
	 */
	public void initCurrentProgressBar() {
		getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

			@Override
			public void onGlobalLayout() {
				// TODO Auto-generated method stub
				if (currentValue < maxvalue) {
					offset = (getWidth() - offsetRight) * currentValue / maxvalue;
				} else {
					offset = getWidth() - offsetRight;
				}
			}
		});

	}

	/**
	 * 獲取“100%”的寬度
	 */
	public void getTextWidth() {
		Paint paint = new Paint();
		Rect rect = new Rect();
		paint.setTextSize(textSize);
		paint.setAntiAlias(true);
		paint.getTextBounds("100%", 0, "100%".length(), rect);
		offsetRight = rect.width() + 5;
	}
}
這就是實現程式碼,程式碼不多,註解也有,不是很難。使用時只需傳入檔案最大值,當前下載了多少就能自動計算出百分比。如果迴圈傳入,就實現了動態跑動的效果。

三:Activity佈局檔案 activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:ywl="http://schemas.android.com/apk/res/com.ywl5320.downloadprogressdemo" <!-- 這就是為自定義屬性新增名稱空間,注意res後的是:程式包名-->
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/no3_white"
    tools:context="${relativePackage}.${activityClass}" >
    
    <TextView 
        android:id="@+id/tv_start"
        android:layout_width="match_parent"
        android:layout_height="50dip"
        android:layout_below="@+id/rl_progress"
        android:layout_marginTop="40dip"
        android:layout_marginLeft="20dip"
        android:layout_marginRight="20dip"
        android:gravity="center"
        android:background="@drawable/btn_blue_selector"
        android:text="開始"/>
    
    <RelativeLayout
        android:id="@+id/rl_progress"
        android:layout_width="match_parent"
        android:layout_marginLeft="20dip"
        android:layout_marginRight="20dip"
        android:layout_marginTop="30dip"
        android:layout_height="50dip">
        <TextView
            android:id="@+id/tv_size"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dip"
            android:textColor="@color/no5_gray_silver"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/tv_speed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginTop="6dip"
            android:textColor="@color/no5_gray_silver"
            android:textSize="12sp" />

        <com.ywl5320.downloadprogressdemo.downloadview.DownLoadProgressbar
            android:id="@+id/dp_game_progress"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            ywl:dptextsize="14sp" <!-- 這裡設定控制元件的字型大小為14sp -->
            android:layout_below="@+id/tv_size">
        </com.ywl5320.downloadprogressdemo.downloadview.DownLoadProgressbar>
    </RelativeLayout>

</RelativeLayout>

程式中的檔案大小,當前下載量和下載速度,都是在這裡佈局的,用的時候可以動態設定就行了,也可以把這個佈局檔案封裝為listview的item佈局檔案,那樣就可以製作下載列表了。

四:MainAcativity.java

package com.ywl5320.downloadprogressdemo;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

import com.ywl5320.downloadprogressdemo.downloadview.DownLoadProgressbar;

public class MainActivity extends Activity {

	private TextView mStart;
	private TextView mSize;
	private TextView mSpeed;
	private DownLoadProgressbar mProgress;
	private int max = 100; //總的大小
	private int current = 0; //當前下載大小
	private String speed = "1"; //下載速度

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mStart = (TextView) findViewById(R.id.tv_start);
		mProgress = (DownLoadProgressbar) findViewById(R.id.dp_game_progress);
		mSize = (TextView) findViewById(R.id.tv_size);
		mSpeed = (TextView) findViewById(R.id.tv_speed);
		//初始化下載進度
		mSize.setText(current + "MB/" + max + "MB");
		//初始化下載速度
		mSpeed.setText(speed + "MB/s");
		mStart.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				start();
			}
		});
	}

	//迴圈模擬下載過程
	public void start() {
		if (current <= max) {
			mSize.setText(current + "MB/" + max + "MB");
			mSpeed.setText(speed + "MB/s");
			mProgress.setMaxValue(max);
			mProgress.setCurrentValue(current);
			handler.postDelayed(runnable, 100);
		} else {
			handler.removeCallbacks(runnable);
		}

	}

	Handler handler = new Handler();
	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
			current = current + 1;
			start();
		}
	};

}

就這樣一個簡單實用的下載百分比進度條就實現了,有需要可以直接用就行: 免費下載地址