写在前面

这是在发表的处女座,这个想法也停留在脑海中很久了,一直拖到现在(懒癌发作2333),先自我介绍一番,一枚刚毕业不久的Android程序猿,初出茅庐的Android小生,之前一直在CSDN发表技术文章,但感觉相比之下的整体体验会稍好一些,希望能够在留下对自己技术的成长足迹,总结开发过程中的一些小小心得,这也是一个新的开始,互相学习,无量变何以质变。
 
 


正文

概述

日常开发经常会有遇到使用进度条的地方,有些场景会需要使用圆形百分比进度条来更优雅地表示当前的进度,并赋予一些入场动画,使得页面更有活力(比如一些运动App,表示能量的进度条,消耗卡路里的进度条等等),给用户一种不断累积的视觉感:

image

 

需要定制的特性

1.设置圆弧半径

2.背景圆弧的粗细

3.进度圆弧的粗细

4.设置进度颜色

5.中心文字大小 颜色 内容

6.进度值 最大值

7.动画时间
 

实现思路

一共可以分为3部分来绘制: 底部的圆、进度弧线、中心文本,最终结合动画达成效果。


1)绘制底部圆

底部绘制圆采用drawCircle(float cx, float cy, float radius, Paint paint)

代码如下:

/** * 绘制后面的整圆 */paint.setStyle(Paint.Style.STROKE); //设置空心paint.setStrokeWidth(bgStrokeWidth); //设置圆环的宽度paint.setColor(roundColor);paint.setAntiAlias(true);  //消除锯齿canvas.drawCircle(center, center, radius, paint);

 
 


2)绘制中心文本

中心文本采用drawText(String text, float x, float y, Paint paint)

这里需要解决一个点,如何计算文本的位置,让文本整体居中?
可以计算整个View的中心点的坐标,可以通过Paint的 measureText 方法获得文本的宽度,centerX-textWidth/2 即可得到文本的left,同理根据centerY - textSize/2 即可得到文本的top。

代码如下:

/**  * 画进度百分比文本*/paint.setStrokeWidth(0);paint.setColor(textColor);paint.setTextSize(textSize);paint.setTypeface(Typeface.DEFAULT); //设置字体if (!TextUtils.isEmpty(centerText)) {     //如果是设置文本内容,则直接测量文本长度并绘制     float textWidth = paint.measureText(centerText);     canvas.drawText(centerText, center - textWidth / 2, center + textSize / 2, paint); //画出进度百分比} else {     //如果是设置百分比,则计算百分比并绘制     int percent = (int) (((float) progressValue / (float) maxValue) * 100);  //中间的进度百分比,先转换成float在进行除法运算,不然都为0     float textWidth = paint.measureText(percent + "%");   //测量字体宽度,我们需要根据字体的宽度设置在圆环中间     if (percent != 0) {        canvas.drawText(percent + "%", center - textWidth / 2, center + textSize / 2, paint); //画出进度百分比     }}

 
 


3)绘制进度弧线

从效果图中可以看出,进度条是从底部中心开始向两边展开,可以通过ValueAnimator让当前进度(接下来以curProgress代称)从0开始增长至最终的目标进度

进度条的绘制采用 canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
oval 弧形所在的区域,可以理解为弧形的边界
startAngle 弧形的起始弧度 以x轴正方向为0°为起始点计算
sweepAngle 弧形的长度 以startAngle为起始点计算,顺时针方向扫过的角度
useCenter 设为true时会将圆心与弧线包围的区域也同时绘制,类似扇形效果
paint 绘制弧形的画笔
 
画了张示意图方便理解:

drawArc示意图.png

为了实现从底部向上绘制弧线,drawArcsweepAngle 肯定是(progress/max)*360,startAngle则要通过计算来动态变更。
以0°为界限,180*(curProgress/maxProgress)则表示sweepAngle的一半的长度假如当前curProgress/maxProgress 大于0.5,说明进度条弧度的一边已经超过了0°的界限,说明进度条弧度的startAngle要小于0且超过的这部分的长度 = -(180*(curProgress/maxProgress) - 90);假如当前curProgress/maxProgress 小于0.5,说明进度条弧度的一边未超过0°的界限,说明进度条弧度的startAngle要大于0且超过的这部分的长度 = 90 - 180*(curProgress/maxProgress);最终其实都可以采用90 - 180*(curProgress/maxProgress) 的计算得到当前的startAngle

代码如下:

/** 绘制有效的进度条弧线*///设置圆环的宽度paint.setStrokeWidth(progressStrokeWidth);//设置进度的颜色paint.setColor(progressColor);paint.setStrokeCap(Paint.Cap.ROUND);//用于定义的圆弧的形状和大小的界限RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);paint.setStyle(Paint.Style.STROKE);//根据进度画圆弧canvas.drawArc(oval, 90 -180 * ((float) progressValue / (float) maxValue), 360 * progressValue / maxValue, false, paint);

 
 


4)入场动画

只需要不断更新当前的progress值,从0增长到目标进度,然后不断调用invalidate去刷新UI,代码如下:

/**     * 弧线动画     *     * @param last    起始值     * @param current 最终值     * @param length  动画时间 */private void setAnimation(float last, float current, int length) {        ValueAnimator progressAnimator = ValueAnimator.ofFloat(last, current);        progressAnimator.setDuration(length);        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float value = (float) animation.getAnimatedValue();                progressValue = (int) value;                invalidate();            }        });        progressAnimator.start();}

 
 


后续

最近有点沉迷于自定义View,其实很多看似很基础的东西还是很重要的,底层基础决定上层建筑,比如本篇绘制弧线的部分,如何计算出弧线的位置和长度要结合Animator来合成我们的效果,这正是其巧妙之处,虽然都说不重复造轮子,但是有时间还是要研究琢磨造造轮子,毕竟那才是真正能被自己汲取的东西。

CSDN博客:IT_ZJYANG
源码传送门:GitHub-ZJYWidget-YCircleProgressBar
里面还有很多实用的自定义View源码及demo,会长期维护,欢迎Star~ 如有不足之处或建议还望指正,相互学习,相互进步,如果觉得不错动动小手点个喜欢, 谢谢~

关注Android 技术小栈,更多精彩原创

更多相关文章

  1. Android(安卓)高仿微信6.0主界面 带你玩转切换图标变色
  2. Android性能优化之工具介绍
  3. android 字符串绘制示例
  4. 从0开始在Android下开发生活方向盘应用(自绘雷达图)
  5. Android的屏幕刷新原理
  6. Android(安卓)画图 擦除开发
  7. Android硬件加速绘制模型介绍
  8. Android(安卓)自定义View 绘制正N边形
  9. Hackborn的吐槽和Munn的剖析: Android(安卓)graphics低性能背后

随机推荐

  1. 监听网络变化的广播
  2. ubuntu android 真机调试
  3. Android(安卓)Service播放音乐
  4. Handling large/high resolution images
  5. Android(安卓)显示Gif
  6. Android(安卓)BottomNavigationBar 底部
  7. 模拟按键操作的几种方式
  8. 解决adb shell 找不到设备的问题
  9. Android(安卓)中英文切换工具类
  10. Android(安卓)APK安装常见错误