先看一下效果:
有沒有亮瞎你的眼?
嗯...我說結尾的顏色。
先分析下實現的邏輯:我們用一個Drawable對象設置爲button的背景;→Drawable對象我們取它的子類BitmapDrawable的一個實例,BitmapDrawAble需要一個Bitmap對象;→繪製這個bitmap:有一個外邊的框框我們畫一個矩形,進度那條線我們使用繪製一個Path來表現;→當前的進度值乘以矩形的周長是path的長度,根據這個長度和矩形周長的關係,使用path的lineTo,moveTo等函數對其進行設置,然後繪製這個path。→顏色根據進度值改變得到一個變化的顏色。
實現細節:
1,得到矩形寬高:在onclick事件中
w = v.getMeasuredWidth();
h = v.getMeasuredHeight();
2,根據進度得到Path,這裏我是以頂部的中點爲起點順時針計算進度的,這裏可以隨意發揮,周長乘以這個進度得到path的長度,在按照你設計好的起點和方向畫線,遇到頂點時判斷path需不需要拐彎。
/**
* 根據百分比得到路徑
*
* @param pro 0~1之間的一個浮點數
* @return
*/
public Path getPath(float pro) {
pro = pro * (w * 2 + h * 2);
Path p = new Path();
p.moveTo(w / 2, 0);
if (pro < w / 2) {
p.lineTo(w / 2 + pro, 0);
return p;
} else {
p.lineTo(w, 0);
}
if (pro < w / 2 + h) {
p.lineTo(w, (pro - w / 2));
return p;
} else {
p.lineTo(w, h);
}
if (pro < w / 2 + h + w) {
p.lineTo((w - (pro - h - w / 2)), h);
return p;
} else {
p.lineTo(0, h);
}
if (pro < w / 2 + h + h + w) {
p.lineTo(0, h - (pro - w - h - w / 2));
return p;
} else {
p.lineTo(0, 0);
}
p.lineTo(pro - w - h * 2 - w / 2, 0);
return p;
}
3,根據進度得到一個漸變色,漸變色的原理沒有搜到,這裏模擬了一下,RGB顏色讓其中一個或幾個通道的顏色值在一定範圍內漸變。
/**
* 得到顏色梯度中間值 這裏可以自己定義
*
* @param pro 0~1之間的一個浮點數
* @return
*/
public int getColor(float pro) {
int c = Color.argb(255, 100+(int) ((1 - pro) * 130), (int) (pro * 255), 155);
return c;
}
4,得到背景Drawable對象,這裏沒什麼好說的,畫筆設置之前根據進度值得到的顏色,設置不同寬度分別畫path和矩形。
/**
* 得到DrawAble對象
*
* @param path
* @param color
* @return
*/
public Drawable getBgDrawAble(Path path, int color) {
Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Paint paint = new Paint();
paint.setColor(color);
paint.setStrokeWidth(30);
paint.setStyle(Paint.Style.STROKE);
c.drawPath(path, paint);
paint.setStrokeWidth(3);
c.drawRect(0,0,w,h,paint);
BitmapDrawable bd = new BitmapDrawable(b);
return bd;
}
5,這裏模擬一個下載的使用場景:
在onclick事件中開啓一個異步任務:
public void download(View v) {
w = v.getMeasuredWidth();
h = v.getMeasuredHeight();
new DownloadTask(v).execute();
}
class DownloadTask extends AsyncTask<Void, Float, Boolean> {
View v;
public DownloadTask(View v) {
this.v = v;
}
@Override
protected Boolean doInBackground(Void... params) {
for (int i = 0; i <= 200; i++) {
publishProgress(i * 1.0f / 200);
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return true;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
((Button)v).setClickable(false);// 設置按鈕不可點擊
}
@Override
protected void onPostExecute(Boolean integer) {
super.onPostExecute(integer);
((Button)v).setText("下載完成");
((Button)v).setClickable(true);
}
@Override
protected void onProgressUpdate(Float... values) {
float rate = values[0];
int col = getColor(rate);
((Button)v).setTextColor(col);
v.setBackground(getBgDrawAble(getPath(rate), col));
((Button)v).setText("已下載" + (rate < 0.1 ? "0" : "") + (int)(rate*100) + "%");//計算下載進度並設置文字
super.onProgressUpdate(values);
}
}
這個估計是最土的實現方法了,效率神馬的待我腦補相關知識再考慮吧。