自定義View之—漸變進度條

龍行天下 8年前發布 | 12K 次閱讀 軟件開發 Android開發 移動開發

最近項目中用到漸變圓環進度條,自己也寫了一下,用到一些知識,以前沒有用過,使用過程中有一些問題,在此做一下筆記。

漸變顏色其實用到的是顏色數組,然后根據數組計算來的,當然計算是Android系統進行的,不需要我們手動計算,我們只需要設置顏色數組和顏色值對應位置即可。畫圓形漸變用到一個屬性:SweepGradient,他的父類是一個Shader,

由官方文檔看到他有兩個構造函數:

SweepGradient(float cx, float cy, int color0, int color1)
SweepGradient(float cx, float cy, int colors[], float positions[])
  • cx:要畫的圓環的中心點x坐標;
  • cy:要畫的圓環的中心點y坐標;
  • color0:起始顏色值;
  • color1:結束顏色值;
  • colors[]:顏色數組;
  • positions[]:對應顏色值的位置,與顏色值數組個數相等,里面的值均為(0–1)的數字。

先看一張效果圖(圖一):

這就是一張漸變圓環圖,上面的箭頭和數字后面解釋。

我們主要研究第二個構造函數,顏色數組和顏色位置的使用方法。

首先看一個例子:

/**
 * 圓形漸變進度條
 * 相關知識:
 * <p>
 * Created by yuchuan on 16/9/29.
 */

public class CircleGradientProgressbar extends View {

    private final static int DURATION = 3000;
    private int mWidth;
    private int mHeight;
    private int mDiam;

    private int mColorGreen;
    private int mColorYellow;
    private int mColorRed;

    private final float mMaxProgress = 100f;
    //默認進度
    private int mProgress = 80;

    private int mCurrentProgress = 100;
    //進圖條圓環寬度
    private int mProgressStrokeWidth = 10;
    //進度條背景畫筆
    private Paint mCirclePaint;
    //進度條畫筆
    private Paint mProgressPaint;
    private Shader mProgressShader;

    //畫圓所在的距形區域
    private RectF mProgressOval;

    private ValueAnimator mAnimator;

    public CircleGradientProgressbar(Context context) {
        this(context, null);
    }

    public CircleGradientProgressbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {

        mColorGreen = getResources().getColor(R.color.mx_circle_progressbar_green);
        mColorYellow = getResources().getColor(R.color.mx_circle_progressbar_orange);
        mColorRed = getResources().getColor(R.color.mx_circle_progressbar_red);

        mProgressOval = new RectF();

        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(true);
        mCirclePaint.setColor(Color.GRAY);

        mProgressPaint = new Paint();
        //設置抗鋸齒
        mProgressPaint.setAntiAlias(true);
        //設置筆為圓角
//        mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        mProgressPaint.setStyle(Paint.Style.STROKE);

        mAnimator = ValueAnimator.ofFloat(0, 1f);

        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float percent = (float) animation.getAnimatedValue();
                if (percent > 0) {
                    mCurrentProgress = (int) (mProgress * percent);
                    postInvalidate();
                }
            }
        });

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mWidth = getWidth();
        mHeight = getHeight();
        mDiam = Math.min(mWidth, mHeight);
        mProgressStrokeWidth = mDiam / 6;
        drawCircle(canvas);
        drawSweepProgressBar(canvas, mWidth / 2, mHeight / 2);
    }

    private void drawCircle(Canvas canvas) {
        canvas.drawArc(mProgressOval, 0, 360, false, mCirclePaint);
    }

    /**
     * 畫漸變圓環:
     * colorSweep[]: 漸變顏色數組
     * position[]:   每個顏色值的相對位置,個數與顏色數組個數相等
     * 注:位置與漸變顏色值的設置教程見博客:
     *
     * @param canvas 畫布
     * @param cx     圓環中心X坐標
     * @param cy     圓環中心Y坐標
     */
    private void drawSweepProgressBar(Canvas canvas, int cx, float cy) {

        //設置圓環的大小
        mProgressOval.top = cy - mDiam / 4;
        mProgressOval.left = cx - mDiam / 4;
        mProgressOval.bottom = cy + mDiam / 4;
        mProgressOval.right = cx + mDiam / 4;

        //畫漸變顏色
        int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
        float position[] = {0f,0.5f,0.7f};

        mProgressShader = new SweepGradient(cx, cy, colorSweep, position);
        mProgressPaint.setShader(mProgressShader);
        mProgressPaint.setStrokeWidth(mProgressStrokeWidth);
        canvas.drawArc(mProgressOval, 0, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint); // 繪制進度圓弧,這里是藍色

    }

    public void setProgress(int progress) {
        this.mProgress = progress;
        if (mAnimator != null && progress > 0) {
            if (mAnimator.isRunning()) {
                return;
            }
            mAnimator.setDuration((long) (DURATION / mMaxProgress * progress));
            mAnimator.start();
        }
    }
}

效果圖如下:

此時的顏色數組和位置參數為:

int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0f,0.5f,0.7f};

下面我們更改一下顏色值的位置:

int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0.25f,0.5f,0.75f};

效果圖如下:

對比上面兩個圖片我們看到隨著第一個位置的值的增大,第一個顏色值的漸變色開始位置也在向后移動。此時我們畫圓環是從0度開始的,也就是3點鐘的位置開始,順時針開始畫圓環。第一個顏色綠色也是從這個位置開始的。那么我們看看如果我改變開始畫的位置,有什么變化嗎?

我用上面第二組的數據,然后只改變畫圓環的初始位置:

int colorSweep[] = {mColorGreen, mColorYellow, mColorRed};
float position[] = {0.25f,0.5f,0.75f};
canvas.drawArc(mProgressOval, 0, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint);

效果圖如下:

自定義View之—漸變進度條

顯示效果和上面一個是一樣的,只是運行時你會發現,圓環是從(圖一)0.75那個位置開始順時針畫的,并且開始畫的顏色是紅色的,由此判斷,第一個顏色值是用(圖一)0的那個位置順時針開始計算的,那么如果我想從0.75那個位置開始畫并且顏色從綠的開始怎么畫,那你需要將開始畫的角度改為:-90,然后更改顏色數組和顏色位置數組:

int colorSweep[] = {mColorGreen, mColorGreen, mColorYellow, mColorRed, mColorGreen, mColorGreen};
float position[] = {0.1f, 0.25f, 0.5f, 0.751f, 0.75f, 1f};
canvas.drawArc(mProgressOval, -90, ((float) mCurrentProgress / mMaxProgress) * 360, false, mProgressPaint);

效果圖如下:

此時我們看到,綠色是從(圖一)0.75位置開始的,并且圓環也是從這個位置開始畫的,但是此時我的顏色值和位置增加了,主要是后面部分,倒數第二個顏色值是綠色,對應位置是0.75,也是就分段設置顏色值,0.75的位置為綠色,最后一個也是綠色,則說明從0.75之后到1的位置都是綠色,然后0后面的顏色根據位置數組第一個參數開始計算,如果角度不是0就要按照這個計算進行調整。

另外,最后一個例子中相同顏色設置了多個,這個是調節漸變和純色位置的,也就是相同顏色位置間的顏色是純色的,不同顏色值中間的顏色是過度的,自己可以調節一下掌握以下技巧。

 

 

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