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 Android360

   今天偶然看到一个圆盘形的菜单,还可以转动,感觉挺有意思,然后想了想,做了个简单的效果。       思路是这样的,定一个原点和一个半径,圆的四周均匀...

1412
来自专栏柠檬先生

css3 UI 修饰——回顾

1.box-shadow 属性向框添加一个或者多个阴影。   语法: box-shadow: h-shadow v-shadow blur spread col...

1989
来自专栏Android开发指南

裁剪圆形图片原理

2665
来自专栏潇涧技术专栏

Android Heroes Reading Notes 3

《Android群英传》读书笔记 (3) 第六章 Android绘图机制与处理技巧 + 第七章 Android动画机制与使用技巧

692
来自专栏Android开发与分享

【Android】RecyclerView:打造悬浮效果

63010
来自专栏一“技”之长

Android开发之LinearLayout布局详解

        LinaerLayout又被称为线性布局,是Android界面开发中常用的一种容器视图控件。可以使用XML布局文件配置和代码动态创建两种方式来使...

883
来自专栏CodingBlock

Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解

上篇文章介绍了自定义View的创建流程,从宏观上给出了一个自定义View的创建步骤,本篇是上一篇文章的延续,介绍了自定义View中两个必不可少的工具Canvas...

39112
来自专栏Android知识点总结

Android原生绘图之一起画个表

3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

1333
来自专栏云加头条

Android图像处理-像素化的原理及实现

像素化(Pixelization),又称马赛克,是图像处理中非常常见的技术,现阶段已经成为了一种创作手段。本文首先会讲解像素化的实现原理,接着会给出Java版的...

4661
来自专栏移动开发

用path画一个抽象的树叶

源码地址:https://github.com/X-FAN/LeafView 只是个简单的demo,大家可以参考下

1082

扫码关注云+社区