Android开发经验谈Android开发Android开发

Android – 环形进度条

2017-10-30  本文已影响252人  Kotyo

环形进度条

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;
    }
}

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

上一篇下一篇

猜你喜欢

热点阅读