1. 程式人生 > >弧形進度條,用到PorterDuffXfermode

弧形進度條,用到PorterDuffXfermode

UI設計師的審美觀特別的好,做的UI也很好看。

先看設計圖要求

分析:

漸變可以做,文字也都沒什麼問題,但是圓環外邊的小突起怎麼做?用畫小漸變矩形?沒有進度的灰色帶邊框的漸變圓弧怎麼做?

太難了,最終選擇的是用圖片來做

圖片如下,只上傳了上圓環


圖:bgBitmap圖:shadeBitmap圖:混合模式

關鍵點就是PorterDuffXfermode 圖層混合模式 PorterDuff.Mode.DST_OUT

原理:在畫布最底層繪製bgBitmap,然後用shadeBitmap和一個圓弧疊加後的圖層遮蓋bgBitmap,就可以了。由於使用DST_OUT後圓弧和shadeBitmap重疊的部分,shadeBitmap就不會顯示(透明的),bgBitmap就顯示部分了。

下面就是程式碼了:

Xfermodem Xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);

@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bgBitmap, null, bgRect, mPaint1); 先繪製背景bgBitmap,使用shadeBitmap來遮蓋背景bgBitmap

//繪製文字,沒什麼好說的
canvas.drawText("0", srcRect.left-mBound.width(),  srcRect.top+srcRect.height()/2+mBound.height()/2, textPaint);
canvas.drawText("15", srcRect.left-mBound.width(),  srcRect.top-10, textPaint);
canvas.drawText("30", srcRect.left+srcRect.width()/2-mBound.width()/2,  srcRect.top-mBound.height(), textPaint);
canvas.drawText("45", srcRect.left+srcRect.width(),  srcRect.top, textPaint);
canvas.drawText("60", srcRect.left+srcRect.width()+mBound.width(),  srcRect.top+srcRect.height()/2+mBound.height()/2, textPaint);
canvas.drawText("KW", UnitX-unitBound.width()/2, UnitY+unitBound.height()/2, unitPaint);
if(angle>=178){return;}

//將繪製操作儲存到新的圖層,因為影象合成是很昂貴的操作,將用到硬體加速,這裡將影象合成的處理放到離屏快取中進行
        int saveCount = canvas.saveLayer(dstRect, mPaint, Canvas.ALL_SAVE_FLAG);
        //繪製目標圖
        canvas.drawBitmap(shadeBitmap, null, dstRect, mPaint1);

        //設定混合模式
        mPaint.setXfermode(mXfermode);
        //繪製源圖,也就是圓弧
        canvas.drawArc(srcRect, 179, angle, false, mPaint);
        //清除混合模式
        mPaint.setXfermode(null);
        //還原畫布
        canvas.restoreToCount(saveCount);
//上面的做法就是 把shadeBitmap和一個圓弧在一個圖層中進行疊加,圓弧掃過的部分shadeBitmap就不會顯示,然後把這個圖層覆蓋到canvas上,也就是bgBitmap上面,shadeBitmap不顯示的部分,

bgBitmap就顯示出來了
       }

那麼怎麼控制進度呢?當然是控制angle啦,進度0-180 

這是生成繪畫矩形的程式碼

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int width = w>h?w:h;
        int centerX = width/2;
        int centerY = width/2;
        int quarterWidth = width /4;
        srcRect = new RectF(centerX-quarterWidth+25, centerY-quarterWidth+25, centerX+quarterWidth-25, centerY+quarterWidth-25);
        dstRect = new RectF(centerX-quarterWidth, centerY-quarterWidth, centerX+quarterWidth, centerY+quarterWidth);
        bgRect = new RectF(centerX-quarterWidth, centerY-quarterWidth, centerX+quarterWidth, centerY+quarterWidth);
        UnitX = centerX;
        UnitY = centerY;
}

初始化畫筆的時候要設定mPaint1.setAntiAlias(true);mPaint1.setFilterBitmap(true);這樣畫出來的圖形邊緣就不會有齒了。

畫圓弧的畫筆要設定為空心mPaint.setStyle(Paint.Style.STROKE);

最終效果圖:


附:在深圳做Android開發,第2個月,以前沒做過Android開發,如有不足之處,請指出