Android自定義圓形進度條學習

Android中圓形進度條的應用還是挺多的,最近學習實現(xiàn)了圓形進度條。


RingProgressBar

meizu style
思路

要實現(xiàn)圓形進度條,

首先要畫灰色背景圓環(huán)
再畫藍色進度圓環(huán)
再畫進度數(shù)字

搞定。

首先自定義各種屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RingProgressBar">
        <attr name="ringColor" format="color" />
        <attr name="ringProgressColor" format="color" />
        <attr name="textColor" format="color" />
        <attr name="ringWidth" format="dimension" />
        <attr name="textSize" format="dimension" />
        <attr name="max" format="integer" />
        <attr name="showTextProgress" format="boolean" />
        <attr name="style">
            <enum name="STROKE" value="0" />
            <enum name="FULL" value="1" />
        </attr>
    </declare-styleable>
</resources>
初始化各種屬性
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
        ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
        ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
        textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
        textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
        ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
        max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
        textIsDisplayable = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
        style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
        //資源回收
        typedArray.recycle();
初始化三種畫筆
        //背景圓環(huán)畫筆
        ringPaint = new Paint();
        ringPaint.setColor(ringColor);
        ringPaint.setStyle(Paint.Style.STROKE);
        ringPaint.setStrokeWidth(ringWidth);
        ringPaint.setAntiAlias(true);

        //進度圓環(huán)畫筆
        ringProgressPaint = new Paint();
        ringProgressPaint.setColor(ringProgressColor);
        ringProgressPaint.setStrokeWidth(ringWidth);
        ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        ringProgressPaint.setAntiAlias(true);
        switch (style) {
            case STROKE:
                ringProgressPaint.setStyle(Paint.Style.STROKE);
                break;
            case FULL:
                ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                break;
        }

        //進度文字畫筆
        textPaint = new Paint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
抗鋸齒
        ringPaint.setAntiAlias(true);
圓形線條
        ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
圓環(huán)整體圖
圓環(huán)整體圖
畫背景圓環(huán)
        int xCenter = getWidth() / 2;
        int yCenter = getHeight() / 2;

        int radius = (int) (xCenter - ringWidth / 2);
        canvas.drawCircle(xCenter, yCenter, radius, ringPaint);

xCenter:圓心橫坐標
yCenter:圓心縱坐標
radius:半徑
ringPaint:畫筆

疑惑

這里我有點疑惑,為什么半徑是xCenter - ringWidth / 2呢?
我認為半徑應該是xCenter - ringWidth才對,很合理,寬度的一半減去線條寬度,剛好是圓環(huán)的半徑。
懷著疑惑的心情畫了上圖,這里減去圓環(huán)線條寬度的一半或許是因為線條的寬度不可忽略,姑且這樣認為吧,如果有大神看到希望指點迷津。

畫進度圓環(huán)
        RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
        switch (style) {
            case STROKE:
                /*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
                canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
                canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
                break;
            case FULL:
                if (progress != 0) {
                    canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
                }
                break;
        }
左上右下
        RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);

xCenter - radius:矩形距離左邊的距離
yCenter - radius:矩形距離上邊的距離
xCenter + radius:矩形距離右邊的距離
yCenter + radius:矩形距離下邊的距離
其實可以理解為矩形左上角的坐標和右下角的坐標

畫圓弧
        canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);

rectF:圓弧在這個矩形中繪制
-90:圓弧順時針繪制的開始角度
progress * 360 / max:圓弧繪制的角度
false:繪制時是否經(jīng)過圓心,當style設置為STROKE時,是沒有效果的,這里借用兩張圖片,簡單明了
當style設置為FULL,這里設置為false時


false

當style設置為FULL,這里設置為true時


true

ringProgressPaint:畫筆
魅族應用市場下載效果
meizu
        canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
        canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);

將進度分兩次繪制,從底部同時向上繪制進度的一半,就達到了這個效果。

畫進度數(shù)字
        String text = progress + "%";
        float textWidth = textPaint.measureText(text, 0, text.length());
        if (showTextProgress && progress != 0 && style == STROKE) {
            canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
        }
RingProgressBar
package com.goldou.ringprogressbar;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by Administrator on 2017.10.30  0030.
 */

public class RingProgressBar extends View {

    private Paint ringPaint;
    private Paint ringProgressPaint;
    private Paint textPaint;

    private int ringColor;
    private int ringProgressColor;
    private int textColor;

    private float textSize;
    private float ringWidth;

    private int max;
    private int progress;

    private boolean showTextProgress;
    private int style;
    private final int STROKE = 0;
    private final int FULL = 1;

    private Context context;

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

    public RingProgressBar(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RingProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        initAttrs(context, attrs);
        initPaint();
    }

    private void initPaint() {
        ringPaint = new Paint();
        ringPaint.setColor(ringColor);
        ringPaint.setStyle(Paint.Style.STROKE);
        ringPaint.setStrokeWidth(ringWidth);
        ringPaint.setAntiAlias(true);

        ringProgressPaint = new Paint();
        ringProgressPaint.setColor(ringProgressColor);
        ringProgressPaint.setStrokeWidth(ringWidth);
        ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
        ringProgressPaint.setAntiAlias(true);
        switch (style) {
            case STROKE:
                ringProgressPaint.setStyle(Paint.Style.STROKE);
                break;
            case FULL:
                ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                break;
        }

        textPaint = new Paint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setTypeface(Typeface.DEFAULT_BOLD);
    }

    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
        ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
        ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
        textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
        textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
        ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
        max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
        showTextProgress = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
        style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
        //資源回收
        typedArray.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        int xCenter = getWidth() / 2;
        int yCenter = getHeight() / 2;

        int radius = (int) (xCenter - ringWidth / 2);
        canvas.drawCircle(xCenter, yCenter, radius, ringPaint);

        RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
        switch (style) {
            case STROKE:
                /*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
                canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
                canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
                break;
            case FULL:
                if (progress != 0) {
                    canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
                }
                break;
        }

        String text = progress + "%";
        float textWidth = textPaint.measureText(text, 0, text.length());
        if (showTextProgress && progress != 0 && style == STROKE) {
            canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
        }
    }

    public synchronized int getMax() {
        return max;
    }

    public synchronized void setMax(int max) {
        if (max < 0) {
            throw new IllegalArgumentException("max not less than 0");
        }
        this.max = max;
    }

    public synchronized int getProgress() {
        return progress;
    }

    public synchronized void setProgress(int progress) {
        if (progress < 0) {
            throw new IllegalArgumentException("progress not less than 0");
        }
        if (progress > max) {
            progress = max;
        }
        if (progress <= max) {
            this.progress = progress;
            postInvalidate();
        }
    }

    public int getRingColor() {
        return ringColor;
    }

    public void setRingColor(int ringColor) {
        this.ringColor = ringColor;
    }

    public int getRingProgressColor() {
        return ringProgressColor;
    }

    public void setRingProgressColor(int ringProgressColor) {
        this.ringProgressColor = ringProgressColor;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    public float getRingWidth() {
        return ringWidth;
    }

    public void setRingWidth(float roundWidth) {
        this.ringWidth = roundWidth;
    }
}
最后

有什么解釋不對還望各位大神指正

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容