美文网首页
Android 自定义 View 之 圆形 & 方形 进度条

Android 自定义 View 之 圆形 & 方形 进度条

作者: 熊er | 来源:发表于2017-07-22 12:34 被阅读0次

    效果

    1.gif

    实现

    圆形进度条
    • attrs
    <declare-styleable name="CircleProgress">
            <attr name="cpRadius" format="dimension" />
            <attr name="cpColor" format="color" />
     </declare-styleable>
    
    • CircleProgress.java
    /**
     * 圆形进度条
     *
     * @author gavin.xiong 2017/7/18
     */
    public class CircleProgress extends View {
    
        /**
         * 半径
         */
        private int mRadius;
        /**
         * 宽
         */
        private int mWidth;
        /**
         * 高
         */
        private int mHeight;
        /**
         * 高
         */
        private Paint mPaint;
        /**
         * 进度(最大100)
         */
        private float mProgress = 0;
    
        public CircleProgress(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgress);
            mRadius = ta.getDimensionPixelSize(R.styleable.CircleProgress_cpRadius,
                    (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 28f, getResources().getDisplayMetrics()));
            int color = ta.getColor(R.styleable.CircleProgress_cpColor, 0x40ffffff);
            ta.recycle();
    
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setColor(color);
            mPaint.setStyle(Paint.Style.FILL);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int specMode = MeasureSpec.getMode(widthMeasureSpec);
            int specSize = MeasureSpec.getSize(widthMeasureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                mWidth = specSize;
            } else {
                mWidth = defaultRadius() * 2;
            }
            specMode = MeasureSpec.getMode(heightMeasureSpec);
            specSize = MeasureSpec.getSize(heightMeasureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                mHeight = specSize;
            } else {
                mHeight = defaultRadius() * 2;
            }
            setMeasuredDimension(mWidth, mHeight);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (mProgress < 0 || mProgress > 100) {
                return;
            }
            RectF oval = new RectF(mWidth / 2 - mRadius, mHeight / 2 - mRadius, mWidth / 2 + mRadius, mHeight / 2 + mRadius);
            // 根据进度画圆弧 - 反向
            canvas.drawArc(oval, mProgress / 100 * 360 - 90, 360 - mProgress / 100 * 360, true, mPaint);
        }
    
        /**
         * 设置进度 最大值100
         */
        public void setProgress(float progress) {
            this.mProgress = progress;
            postInvalidate();
        }
    
        private int defaultRadius() {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 28f, getResources().getDisplayMetrics());
        }
    }
    
    方形进度条
    • attrs
    <declare-styleable name="SquareProgress">
            <attr name="spColor" format="color" />
    </declare-styleable>
    
    • SquareProgress.java
    /**
     * 方形进度条
     *
     * @author gavin.xiong 2017/7/22
     */
    public class SquareProgress extends View {
    
        private static final String TAG = "SquareProgress";
    
        /**
         * 宽
         */
        private int mWidth;
        /**
         * 高
         */
        private int mHeight;
        /**
         * 高
         */
        private Paint mPaint;
        /**
         * 进度(最大100)
         */
        private double mProgress = 0;
    
        public SquareProgress(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SquareProgress);
            int color = ta.getColor(R.styleable.SquareProgress_spColor, 0x40ffffff);
            ta.recycle();
    
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setColor(color);
            mPaint.setStyle(Paint.Style.FILL);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int specMode = MeasureSpec.getMode(widthMeasureSpec);
            int specSize = MeasureSpec.getSize(widthMeasureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                mWidth = specSize;
            } else {
                mWidth = defaultLength();
            }
            specMode = MeasureSpec.getMode(heightMeasureSpec);
            specSize = MeasureSpec.getSize(heightMeasureSpec);
            if (specMode == MeasureSpec.EXACTLY) {
                mHeight = specSize;
            } else {
                mHeight = defaultLength();
            }
            setMeasuredDimension(mWidth, mHeight);
        }
    
        private int defaultLength() {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 56f, getResources().getDisplayMetrics());
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (mProgress < 0 || mProgress >= 100) {
                return;
            }
    
            // 偏移角度
            double x = mProgress / 100 * 2 * Math.PI;
            double ratio = mWidth * 1D / mHeight;
    
            Path path = new Path();
            path.moveTo(mWidth / 2, mHeight / 2);
    
            if (mProgress <= 25) {
                Log.e(TAG, "第一象限");
                if (Math.tan(x) <= ratio) {
                    Log.e(TAG, "上横边");
                    path.lineTo(mWidth / 2 + (float) Math.tan(x) * mHeight / 2, 0);
                    path.lineTo(mWidth, 0);
                    path.lineTo(mWidth, mHeight);
                    path.lineTo(0, mHeight);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                } else {
                    Log.e(TAG, "上竖边");
                    path.lineTo(mWidth, mHeight / 2 - (float) Math.tan(Math.PI / 2 - x) * mWidth / 2);
                    path.lineTo(mWidth, mHeight);
                    path.lineTo(0, mHeight);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                }
            } else if (mProgress <= 50) {
                Log.e(TAG, "第二象限");
                if (Math.tan(x - Math.PI / 2) <= 1 / ratio) {
                    Log.e(TAG, "下竖边");
                    path.lineTo(mWidth, mHeight / 2 + (float) Math.tan(x - Math.PI / 2) * mWidth / 2);
                    path.lineTo(mWidth, mHeight);
                    path.lineTo(0, mHeight);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                } else {
                    Log.e(TAG, "下横边");
                    path.lineTo(mWidth / 2 + (float) Math.tan(Math.PI - x) * mHeight / 2, mHeight);
                    path.lineTo(0, mHeight);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                }
            } else if (mProgress <= 75) {
                Log.e(TAG, "第三象限");
                if (Math.tan(x - Math.PI) <= ratio) {
                    Log.e(TAG, "下横边");
                    path.lineTo(mWidth / 2 - (float) Math.tan(x - Math.PI) * mHeight / 2, mHeight);
                    path.lineTo(0, mHeight);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                } else {
                    Log.e(TAG, "下竖边");
                    path.lineTo(0, mHeight / 2 + (float) Math.tan(Math.PI * 3 / 2 - x) * mWidth / 2);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                }
            } else {
                Log.e(TAG, "第四象限");
                if (Math.tan(x - Math.PI * 3 / 2) <= 1 / ratio) {
                    Log.e(TAG, "上竖边");
                    path.lineTo(0, mHeight / 2 - (float) Math.tan(x - Math.PI * 3 / 2) * mWidth / 2);
                    path.lineTo(0, 0);
                    path.lineTo(mWidth / 2, 0);
                } else {
                    Log.e(TAG, "上横边");
                    path.lineTo(mWidth / 2 - (float) Math.tan(Math.PI * 2 - x) * mHeight / 2, 0);
                    path.lineTo(mWidth / 2, 0);
                }
            }
    
            path.close();
            canvas.drawPath(path, mPaint);
        }
    
        /**
         * 设置进度 最大值100
         */
        public void setProgress(float progress) {
            this.mProgress = progress;
            postInvalidate();
        }
    }
    

    相关文章

      网友评论

          本文标题:Android 自定义 View 之 圆形 & 方形 进度条

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