Android – 环形进度条

作者: Kotyo | 来源:发表于2017-10-30 10:15 被阅读252次

    环形进度条

    ring_circle_progress.gif

    如上图所示,之所以想到写这个,因为项目中有这样的需求,所以自己就去琢磨琢磨该怎么去实现这个需求。
    实现思路:
    ① 画个圆弧
    ② 圆弧上画个圆
    ③ 画进度条
    ④ 在圆弧的中心绘制进度值

    好了,思路已经有了,我们现在一个一个来实现。

    画个圆弧

    canvas.drawArc(rectF, 45, 270, false, mRingPaint);
    

    这样就画了一个我们需要的圆弧。

    圆弧上画个圆
    画圆就需要圆心和半径。半径比较好得到。这里就半径用到了点数学上的知识。

     float radius = (float) ((width - mArcDis - mArcDis) / 2);
     float pointX = (float) (mCircleX + radius * Math.cos(mSwipeAngle * 3.14 / 180));
     float pointY = (float) (mCircleY + radius * Math.sin(mSwipeAngle * 3.14 / 180));
    

    画进度条
    这里的进度条,就是重新绘制一个重合的圆弧

    canvas.drawArc(rectF, 45, mSwipeAngle-45, false, mSwipePaint);
    

    在圆弧的中心绘制进度值

    float v = mTextPaint.measureText(String.valueOf((int) Math.floor((float) (mSwipeAngle - 45) / 270 * 100)));
    canvas.drawText(String.valueOf((int)Math.floor((float)(mSwipeAngle-45)/270*100)),mCircleX-(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mTextPaint);
    canvas.drawText("%",mCircleX+(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mPercentPaint);
    

    下面给出全部代码以供参考:

    public class CircleRingView extends View {
        private int mArcDis;
        private Paint mRingPaint;
        private Paint mPointPaint;
        private int mPointAngle;
        private float mCircleX;
        private float mCircleY;
        private int mSwipeAngle=45;
    
        private Handler mHandler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (mSwipeAngle == mPointAngle) {
                    mHandler.removeMessages(0);
                }else {
                    ++mSwipeAngle;
                    postInvalidate();
                }
            }
        };
        private Paint mSwipePaint;
        private Paint mTextPaint;
        private Paint mPercentPaint;
    
        public CircleRingView(Context context) {
            this(context, null);
        }
    
        public CircleRingView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CircleRingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initParams(context);
        }
    
        private void initParams(Context context) {
            //圆弧Paint
            mRingPaint = new Paint();
            mRingPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 3));
            mRingPaint.setAntiAlias(true);
            mRingPaint.setStyle(Paint.Style.STROKE);
            mRingPaint.setColor(ContextCompat.getColor(context, R.color.white));
            //圆弧上的圆的Paint
            mPointPaint = new Paint();
            mPointPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
            mPointPaint.setAntiAlias(true);
            mPointPaint.setStyle(Paint.Style.FILL);
            mPointPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
            //进度条Paint
            mSwipePaint = new Paint();
            mSwipePaint.setStrokeWidth(Px2DpUtil.dp2px(context,3));
            mSwipePaint.setAntiAlias(true);
            mSwipePaint.setStyle(Paint.Style.STROKE);
            mSwipePaint.setColor(ContextCompat.getColor(context, R.color.bg_gradient_start));
    
            //进度值Paint
            mTextPaint = new Paint();
            mTextPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
            mTextPaint.setAntiAlias(true);
            mTextPaint.setStyle(Paint.Style.FILL);
            mTextPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
            mTextPaint.setTextSize(Px2DpUtil.sp2px(context,40));
    
            //百分号Paint
            mPercentPaint = new Paint();
            mPercentPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
            mPercentPaint.setAntiAlias(true);
            mPercentPaint.setStyle(Paint.Style.FILL);
            mPercentPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
            mPercentPaint.setTextSize(Px2DpUtil.sp2px(context,25));
            //Rectf所需要
            mArcDis = Px2DpUtil.dp2px(context, 20);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int width = getWidth();
            int height = getHeight();
            RectF rectF = new RectF();
            rectF.left = mArcDis;
            rectF.top = mArcDis;
            rectF.right = width - mArcDis;
            rectF.bottom = height - mArcDis;
            canvas.rotate(90, width / 2, height / 2);
            //正常圆弧
            canvas.drawArc(rectF, 45, 270, false, mRingPaint);
            if (mSwipeAngle>=0&&mSwipeAngle <= 45) {
                mSwipeAngle = 45;
                mPointAngle=45;
            } else if (mSwipeAngle > 315 & mSwipeAngle <= 360) {
                mSwipeAngle = 315;
                mPointAngle = 315;
            }
            mCircleX = width / 2;
            mCircleY = height / 2;
            if(mSwipeAngle<=mPointAngle) {
                float radius = (float) ((width - mArcDis - mArcDis) / 2);
                float pointX = (float) (mCircleX + radius * Math.cos(mSwipeAngle * 3.14 / 180));
                float pointY = (float) (mCircleY + radius * Math.sin(mSwipeAngle * 3.14 / 180));
                //进度圆弧,模仿进度条
                canvas.drawArc(rectF, 45, mSwipeAngle-45, false, mSwipePaint);
                //圆弧上的圆
                canvas.drawCircle(pointX, pointY, Px2DpUtil.dp2px(getContext(), 10), mPointPaint);
                canvas.rotate(-90, width / 2, height / 2);
                //测量文本宽度
                float v = mTextPaint.measureText(String.valueOf((int) Math.floor((float) (mSwipeAngle - 45) / 270 * 100)));
                //绘制文本
                canvas.drawText(String.valueOf((int)Math.floor((float)(mSwipeAngle-45)/270*100)),mCircleX-(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mTextPaint);
                //绘制百分号
                canvas.drawText("%",mCircleX+(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mPercentPaint);
                mHandler.sendEmptyMessageDelayed(0, 10);
            }
        }
        //需要画的进度值
        public void setProgressValue(int value){
            int swipeAngle = (int) (((float)value / 100) * 360);
            mPointAngle=  swipeAngle;
            mHandler.sendEmptyMessageDelayed(0, 10);
        }
        //停止绘制View
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            mHandler.removeMessages(0);
            mHandler=null;
        }
    }
    

    到这里,整个控件的实现方法就都写完了。

    相关文章

      网友评论

        本文标题:Android – 环形进度条

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