自定義View之炫麗的進度條

Android自定義View之炫麗的進度條

好久沒有寫Blog了,昨天意外看到自己無意中寫的一篇文章,訪問量都有1k+,突然之間覺得寫博客,分享知識是一件多麼幸福的事情!今天我給大家分享一個自定義view來繪製一個項目中經常用的炫麗立體效果的進度條.雖然不怎麼有難度,但是項目中經常用到,希望能幫助大家項目中的一些問題,幫到大家。
這裏寫圖片描述

代碼下載地址:http://download.csdn.net/detail/zgkxzx/9762403

  • 實現原理
    主要是通過Paint的setXfermode(Xfermode xfermode) 圖像混合模式,關於paint的混合模式的知識,小編就不在這裏科普了,自己到百度上面谷歌一下就知道了。下面我們找重點的地方講解。如下,多種混合模式的效果圖:
    這裏寫圖片描述
    這裏,我們用的的模式是SRC_IN,從效果圖中,我們很清晰看出,當SRC是藍色正方形圖片,DST爲橙色圓形圖片時,SRC_IN效果,即爲當SRC與DST重疊發生,交集部分爲兩圖交集區域,並展現出SRC交集區域。這裏,我們項目中SRC爲
    這裏寫圖片描述
    DST資源爲通過畫布畫的扇形圖像,由於圖片源SRC是一張切圖,我們不容易控制進度,那麼我們通過控制扇形的區域,來實現整體畫布的進度條的控制。如下圖,沒有找到比較好的作圖工具,自己用Galaxy Note機手繪圖形進行分析(畫的不好,不要吐槽~~)。
    這裏寫圖片描述
    當DST扇形(紅色區域)在畫布上掃過,與SRC的交集部分,即畫布上面最終展現的區域(紫色區域),這裏的扇形起始邊是-270度。我們可以根據實際需要進行調整。

    好了,我們不多說了,直接上源碼分析。

  • 代碼實現

自定義View的步驟一般是onMeasure,onLayout,onDraw,這裏我們只需要測量和繪製就行了。

第一步:初始化參數

//背景圖片和進度條圖片
    private Bitmap bgBmp;
    private Bitmap bgProcess;

    private PorterDuffXfermode mMode;
    private Paint mXferPaint;
    private RectF mOval;
    private Paint mTextPaint;
    //百分比
    private int mPercent;
    //邊長
    private int sideLength;
    //縮放比例
    private float scale = 1.0f;
    private void init() {
        bgBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ring_bg);
        if (processImg != null) {
            bgProcess = ((BitmapDrawable) processImg).getBitmap();
        } else
            bgProcess = BitmapFactory.decodeResource(getResources(), R.mipmap.ring_bg_1);

        mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);

        mXferPaint = new Paint();
        mXferPaint.setColor(Color.GREEN);
        mXferPaint.setXfermode(mMode);
        mXferPaint.setAntiAlias(true);

        mOval = new RectF();
        mOval.left = 0;
        mOval.top = 0;
        mPercent = 0;

        mTextPaint = new Paint();
        mTextPaint.setColor(textColor);
        mTextPaint.setTextSize(textSize);
        mTextPaint.setAntiAlias(true);
        Typeface font = Typeface.createFromAsset(context.getAssets(), textFont != null ? textFont : DEFAULR_FONT);
        mTextPaint.setTypeface(font);


    }

在初始化中,主要是對需要繪畫的幾個畫筆進行了初始化。這裏比較重要的是我們用的的PorterDuffXfermode混合圖像模式,在這裏採用了SRC_IN模式。畫筆畫出的扇形和原始進度條圖片發生交集後,顯示原始進度條圖片的部分。在設計進度條之前,小編考慮到可擴展性,本來是準備採用DST_IN模式,這樣進度條顯示部分爲交集的扇形部分,這樣進度條的顏色通過xml倒是很方便配置,但是進度條通過drawArc方法畫出來的是屏幕效果圖,效果沒有切片能展現立體的效果。

第二步:onMeasure方法實現測量

   int widthMode = MeasureSpec.getMode(widthMeasureSpec);
   int widthSize = MeasureSpec.getSize(widthMeasureSpec);
   int heightMode = MeasureSpec.getMode(heightMeasureSpec);
   int heightSize = MeasureSpec.getSize(heightMeasureSpec);

   int width;
   int height;

   int bgWidth = bgBmp.getWidth();
   int bgHight = bgBmp.getHeight();

   if (widthMode == MeasureSpec.EXACTLY) {
       width = widthSize;
   } else {
       width = bgWidth;
   }

   if (heightMode == MeasureSpec.EXACTLY) {
       height = heightSize;
   } else {
       height = bgHight;
   }
   //得到邊長,這裏默認進度條爲正方形的控件
   sideLength = Math.min(width, height);
   //計算比例縮放係數
   scale = (float) sideLength / bgWidth;

   setMeasuredDimension(sideLength, sideLength);

在測量部分,如果採用包裹方式,控件的大小爲原切片背景大大小;如果EXACTLY方式,那麼原切片貨更加精確的長寬進行比例縮放。

第三步:關鍵部分onDraw方法的實現

    //矩陣運算 主要是根據xml的設置對原切片進行比例縮放
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);
    mXferPaint.setXfermode(null);
    canvas.drawBitmap(bgBmp, matrix, mXferPaint);

    //將繪製操作保存到新的圖層(離屏緩存)
    int saveCount = canvas.saveLayer(0, 0, sideLength, sideLength, null, Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    mOval.left = 0;
    mOval.top = 0;
    mOval.right = sideLength;
    mOval.bottom = sideLength;
    mXferPaint.setXfermode(null);

    //繪製扇形區域,關於-235,290這個角度,根據實際切片的角度填寫,找美工妹子要就行了~~~
    canvas.drawArc(mOval, -235, 290 * mPercent / MAX_PROCESS, true, mXferPaint);

    mXferPaint.setXfermode(mMode);
    canvas.drawBitmap(bgProcess, matrix, mXferPaint);

    //繪製進度字
    String text = mPercent + "";
    canvas.drawText(text, 0, text.length(),
                sideLength / 2 - ViewUtil.getTextWidth(mTextPaint, text) / 2,
                sideLength / 2 + ViewUtil.getTextHeight(mTextPaint, text) / 2,
                mTextPaint);
    canvas.restoreToCount(saveCount);

至此,代碼部分也說完了,此自定義view並不怎麼複雜,但是工程中經常用到,希望能幫到大家,一起學習進步…
本來是準備代碼在Github和csdn各上傳一份便於大家參考,可惜最近Github連接不上去了。
代碼下載地址:http://download.csdn.net/detail/zgkxzx/9762403

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章