Material Design學習之 ProgreesBar
轉載奇怪註明出處:王亟亟的大牛之路
繼續我們Material Design的內容,這一篇講的是進度條,上一篇是Switch地址例如以下:http://blog.csdn.net/ddwhan0123/article/details/50592579
進度和動態
在用戶能夠查看並與內容進行交互之前。盡可能地降低視覺上的變化,盡量使應用載入過程令人愉快。每次操作僅僅能由一個活動指示器呈現。比如,對於刷新操作,你不能即用刷新條,又用動態圓圈來指示。
指示器類型
在操作中,對於完畢部分能夠確定的情況下,使用確定的指示器,他們能讓用戶對某個操作所須要的時間有個高速的了解。
在操作中。對於完畢部分不確定的情況下。用戶須要等待一定的時間。無需告知後用戶臺的情況以及所需時間,這時能夠使用不確定的指示器。
指示器的類型有兩種:線形進度指示器和圓形進度指示器。
你能夠使用當中不論什麽一項來指示確定性和不確定性的操作。
線形進度指示器
線形進度指示器應始終從 0% 到 100% 顯示。絕不能從高到低反著來。
假設一個隊列裏有多個正在進行的操作,使用一個進度指示器來指示總體的所須要等待的時間。
這樣,當指示器達到 100% 時,它不會返回到0%再又一次開始。
線形進度條應該放置在頁眉或某塊區域的邊緣。
貼2個官方的演示:
條狀的
環狀的
樣例的實現
高防高仿,包結構:
OK,我們來看下代碼(解釋就解釋 環狀的。條狀的比較簡單)。
final static String ANDROIDXML = "http://schemas.android.com/apk/res/android" ;
int backgroundColor = Color.parseColor("#1E88E5");
public ProgressBarCircularIndeterminate(Context context, AttributeSet attrs) {
super(context, attrs);
setAttributes(attrs);
}
21-30,構造函數以及調用初始化的方法
protected void setAttributes(AttributeSet attrs){
setMinimumHeight(Utils.dpToPx(32 , getResources()));
setMinimumWidth(Utils.dpToPx(32, getResources()));
//Set background Color
// Color by resource
int bacgroundColor = attrs.getAttributeResourceValue(ANDROIDXML,"background",-1);
if(bacgroundColor != -1){
setBackgroundColor(getResources().getColor(bacgroundColor));
}else{
// Color by hexadecimal
int background = attrs.getAttributeIntValue(ANDROIDXML, "background", -1);
if (background != -1)
setBackgroundColor(background);
else
setBackgroundColor(Color.parseColor("#1E88E5"));
}
setMinimumHeight(Utils.dpToPx(3, getResources()));
}
33-55行,獲取xml的參數設置顏色,設置大小的最小值。
protected int makePressColor(){
int r = (this.backgroundColor >> 16) & 0xFF;
int g = (this.backgroundColor >> 8) & 0xFF;
int b = (this.backgroundColor >> 0) & 0xFF;
// r = (r+90 > 245) ? 245 : r+90;
// g = (g+90 > 245) ? 245 : g+90;
// b = (b+90 > 245) ? 245 : b+90;
return Color.argb(128,r, g, b);
}
61-79行,顏色漸變的實現,第一次出現時調用。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(firstAnimationOver == false)
drawFirstAnimation(canvas);
if(cont > 0)
drawSecondAnimation(canvas);
invalidate();
}
72-81行。詳細繪制的操作,由於要推斷是否第一次,所以調用了2種不同的方法,我們一個個看。
float radius1 = 0;
float radius2 = 0;
int cont = 0;
boolean firstAnimationOver = false;
/**
* Draw first animation of view
* @param canvas
*/
private void drawFirstAnimation(Canvas canvas){
if(radius1 < getWidth()/2){
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(makePressColor());
radius1 = (radius1 >= getWidth()/2)? (float)getWidth()/2 : radius1+1;
canvas.drawCircle(getWidth()/2, getHeight()/2, radius1, paint);
}else{
Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas temp = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(makePressColor());
temp.drawCircle(getWidth()/2, getHeight()/2, getHeight()/2, paint);
Paint transparentPaint = new Paint();
transparentPaint.setAntiAlias(true);
transparentPaint.setColor(getResources().getColor(android.R.color.transparent));
transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
if(cont >= 50){
radius2 = (radius2 >= getWidth()/2)? (float)getWidth()/2 : radius2+1;
}else{
radius2 = (radius2 >= getWidth()/2-Utils.dpToPx(4, getResources()))? (float)getWidth()/2-Utils.dpToPx(4, getResources()) : radius2+1;
}
temp.drawCircle(getWidth()/2, getHeight()/2, radius2, transparentPaint);
canvas.drawBitmap(bitmap, 0, 0, new Paint());
if(radius2 >= getWidth()/2-Utils.dpToPx(4, getResources()))
cont++;
if(radius2 >= getWidth()/2)
firstAnimationOver = true;
}
}
83-121,第一次繪制會調用的方法。
假設圓的radius有大小則依據尺寸來繪畫沒有就依據空間大小來設定大小(一開始肯定是0。然後慢慢自增,也就是我們那個灰色圈漸漸變大的效果)
當增長到一定程度了,就開始繪畫空心圓部分的操作,空心圓也是漸漸掏空,直至全然達到控件實體的大小動畫才停止。整個變化過徹骨結束之後把推斷是否為第一次的firstAnimationOver狀態改變
整個過程invalidate();使得邏輯不斷運行。
int arcD = 1;
int arcO = 0;
float rotateAngle = 0;
int limite = 0;
/**
* Draw second animation of view
* @param canvas
*/
private void drawSecondAnimation(Canvas canvas){
if(arcO == limite)
arcD+=6;
if(arcD >= 290 || arcO > limite){
arcO+=6;
arcD-=6;
}
if(arcO > limite + 290){
limite = arcO;
arcO = limite;
arcD = 1;
}
rotateAngle += 4;
canvas.rotate(rotateAngle,getWidth()/2, getHeight()/2);
Bitmap bitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas temp = new Canvas(bitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(backgroundColor);
// temp.drawARGB(0, 0, 0, 255);
temp.drawArc(new RectF(0, 0, getWidth(), getHeight()), arcO, arcD, true, paint);
Paint transparentPaint = new Paint();
transparentPaint.setAntiAlias(true);
transparentPaint.setColor(getResources().getColor(android.R.color.transparent));
transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
temp.drawCircle(getWidth()/2, getHeight()/2, (getWidth()/2)- Utils.dpToPx(4, getResources()), transparentPaint);
canvas.drawBitmap(bitmap, 0, 0, new Paint());
}
131-160,非第一次繪制時的實現,這邊我來解釋下重要部分的邏輯。
if(arcO == limite)
arcD+=6;
if(arcD >= 290 || arcO > limite){
arcO+=6;
arcD-=6;
}
if(arcO > limite + 290){
limite = arcO;
arcO = limite;
arcD = 1;
}
大圓弧最大值為290,滿了就收縮,究竟到頭了都增長,用2個變量做差值反向計算,290為邊界值
canvas.rotate(rotateAngle,getWidth()/2, getHeight()/2);
旋轉操作,每一次角度自增4
分析:
就是第一次進去畫一個從圓心縮放的效果。然後之後都是走290圓弧增大縮小的無限循環計算繪畫,計算這部分邏輯還是有點搞腦子的。大家能夠細致思考思考。
源代碼:https://github.com/ddwhan0123/BlogSample/blob/master/MaterialDesignProgress.zip
Material Design學習之 ProgreesBar