Material Design學習之 ProgreesBar

tc20151681 8年前發布 | 10K 次閱讀 Android開發 移動開發

來自: http://blog.csdn.net/ddwhan0123/article/details/50595766


轉載奇怪注明出處:王亟亟的大牛之路

繼續我們Material Design的內容,這一篇講的是進度條,上一篇是Switch地址如下:http://blog.csdn.net/ddwhan0123/article/details/50592579


進度和動態

在用戶可以查看并與內容進行交互之前,盡可能地減少視覺上的變化,盡量使應用加載過程令人愉快。每次操作只能由一個活動指示器呈現,例如,對于刷新操作,你不能即用刷新條,又用動態圓圈來指示。

指示器類型
在操作中,對于完成部分可以確定的情況下,使用確定的指示器,他們能讓用戶對某個操作所需要的時間有個快速的了解。

在操作中,對于完成部分不確定的情況下,用戶需要等待一定的時間,無需告知后用戶臺的情況以及所需時間,這時可以使用不確定的指示器。

指示器的類型有兩種:線形進度指示器和圓形進度指示器。你可以使用其中任何一項來指示確定性和不確定性的操作。

線形進度指示器

線形進度指示器應始終從 0% 到 100% 顯示,絕不能從高到低反著來。如果一個隊列里有多個正在進行的操作,使用一個進度指示器來指示整體的所需要等待的時間。這樣,當指示器達到 100% 時,它不會返回到0%再重新開始。

線形進度條應該放置在頁眉或某塊區域的邊緣。

貼2個官方的演示:

條狀的
這里寫圖片描述

環狀的

這里寫圖片描述

例子的實現
這里寫圖片描述

高防高仿,包結構:

這里寫圖片描述

OK,我們來看下代碼(解釋就解釋 環狀的,條狀的比較簡單)!

 final static String ANDROIDXML = "

int backgroundColor = Color.parseColor("#1E88E5");


public ProgressBarCircularIndeterminate(Context context, AttributeSet attrs) {
    super(context, attrs);
    setAttributes(attrs);

}</pre> 

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()));


}</pre> 

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();

}</pre> 

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());
}</pre> 

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

</div>

 本文由用戶 tc20151681 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!