Android – 环形进度条

环形进度条

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android干货园

Android源码解析--超好看的下拉刷新动画

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/48...

1012
来自专栏吴小龙同學

Android调用系统相机和相册-填坑篇

之前分享了Android调用系统相机和相册,但是由于国内Android机型繁多,各家都自己的rom,调用系统的还是会出现不少问题: 拍照后照片被旋转 这种...

2726
来自专栏封碎

Android放大镜的实现 博客分类: Android Android

快三个月了没写博客了,因为工作调动,很多经验、心得都没有时间记录下来。现在时间稍微充裕了点,我会尽量抽时间将之前想写而没写的东西补上。进入正题。     ...

541
来自专栏封碎

Android的3D旋转 博客分类: Android AndroidUPBlog

       见过没有用opengl的3D动画,看了一下,是用的Camera实现的,内部机制实际上还是opengl,不过大大简化了使用。        C...

571
来自专栏中国Android研究院

自定义控件之带渐变色的圆形进度条

七夕到了,祝大家七夕节快乐! 今天给大家讲解一个简单的进度条的自定义。首页呢,我们看下效果图:

1202
来自专栏用户画像

绩效考核系统 数据库 sql server 代码

681
来自专栏流媒体

Activity启动流程源码分析

launcher就是android桌面应用程序。也是操作系统启动有第一个app。同时作为其他app的入口。我们找到其源码 android-6.0.0_r1\p...

921
来自专栏曾大稳的博客

Android自定义GLSurfaceView

当我们需要把同一个场景渲染到不同的Surface上时,此时系统GLSurfaceView 就不能满足需求了,所以我们需要自己创建EGL环境来实现渲染操作。 注意...

872
来自专栏非著名程序员

十分钟搞定酷炫动画,Android自定义 View 入门

前几天 Ui 突然给我一个 gif 图说要把这个做成启动动画,看到效果图的我表示一脸懵逼。 ? 好吧,懵逼归懵逼,效果还是要做出来,作为一只没怎么写过动效的猿...

2248
来自专栏转载gongluck的CSDN博客

cocos2dx 象棋

/******************************************************************* * Copyrigh...

2809

扫码关注云+社区