Android自定义圆形进度条学习

作者: 猪爸爸Hulk | 来源:发表于2017-11-03 22:15 被阅读97次

    Android中圆形进度条的应用还是挺多的,最近学习实现了圆形进度条。


    RingProgressBar
    meizu style
    思路

    要实现圆形进度条,

    首先要画灰色背景圆环
    再画蓝色进度圆环
    再画进度数字

    搞定。

    首先自定义各种属性
    <?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();
    
    初始化三种画笔
            //背景圆环画笔
            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);
    
    抗锯齿
            ringPaint.setAntiAlias(true);
    
    圆形线条
            ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
    
    圆环整体图
    圆环整体图
    画背景圆环
            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才对,很合理,宽度的一半减去线条宽度,刚好是圆环的半径。
    怀着疑惑的心情画了上图,这里减去圆环线条宽度的一半或许是因为线条的宽度不可忽略,姑且这样认为吧,如果有大神看到希望指点迷津。

    画进度圆环
            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:绘制时是否经过圆心,当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);
    

    将进度分两次绘制,从底部同时向上绘制进度的一半,就达到了这个效果。

    画进度数字
            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;
        }
    }
    
    最后

    有什么解释不对还望各位大神指正

    相关文章

      网友评论

        本文标题:Android自定义圆形进度条学习

        本文链接:https://www.haomeiwen.com/subject/oqmvpxtx.html