目标
自定义一个环形进度条,可以自定义其最大值、当前进度、背景色、进度色,宽度等信息。
最终效果如下(GIF展示纯色有点问题):
1. 结构分析
- 背景圆环:表示进度条的背景。
- 进度圆环:表示当前进度,根据进度值动态绘制圆环。
- 进度值文本:在圆环中间展示进度。
2. 实现思路
- 定义自定义属性:在 res/values/attrs.xml 中定义自定义属性,以便通过 XML 配置自定义的视图样式。
- 初始化视图元素:在构造函数中,根据传入的属性初始化各种画笔、尺寸和视图元素。
- 绘制视图内容:重写 onDraw 方法,使用画笔绘制背景圆环、进度圆环和文本。
- 支持动态更新进度:提供 setProgress 方法,允许外部动态设置进度,触发视图重绘。
3. 关键技术点解析
我们首先要知道,画圆的基础是有个正方形,或者说有一个正方形的坐标,还要考虑到画笔的宽度,所以我们首先就要确定矩形的大小:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int padding = circleWidth / 2;
rectF.set(padding, padding, w - padding, h - padding);
}
circleWidth
为圆环的宽,也为圆环画笔的宽。
canvas.drawArc
是用于绘制弧形(圆弧)的一种方法,具体参数在前几篇文章已介绍,再次不做赘述。这里主要自定义了进度开始的角度,即 startAngle
属性。
textPaint.setTextAlign(Paint.Align.CENTER)
重点关注下文本画笔的这个属性,这个属性可以保证文本水平居中,而不需要手动去计算文本的宽度信息,先来看下setTextAlign
的作用:
textPaint.setTextAlign(Paint.Align.CENTER)
是 Paint 类中的一个设置文本对齐方式的方法。它用于控制文本在指定位置绘制时的对齐方式,具体来说,它影响了绘制文本时文本的起始点(x,y 坐标)如何被确定。
作用:
Paint.Align
是一个枚举,定义了文本绘制时如何对齐相对于给定的 x
和 y
坐标。常用的对齐方式有三个选项:
-
Paint.Align.LEFT
:- 文本绘制时,文本的起始位置在
x
坐标上。 - 也就是说,文本的左边缘会对齐到
x
坐标。
- 文本绘制时,文本的起始位置在
-
Paint.Align.CENTER
:- 文本绘制时,文本的中心位置与
x
坐标对齐。 - 这意味着文本的中点(水平中心)会与
x
坐标对齐,从而实现水平居中。
- 文本绘制时,文本的中心位置与
-
Paint.Align.RIGHT
:- 文本绘制时,文本的右边缘会对齐到
x
坐标。 - 也就是说,文本的右边缘会对齐到指定的
x
坐标,x
坐标即为文本的终点。
- 文本绘制时,文本的右边缘会对齐到
由于只能做到水平居中,想做到垂直居中还是要计算基线位置的!基线的两种计算方式可以参考前几篇文章,里面有详细的介绍
4. 定义自定义属性
<declare-styleable name="CircularProgressBar">
<!-- 进度条的最大值 -->
<attr name="maxProgress" format="integer"/>
<!-- 当前进度 -->
<attr name="progress" format="integer"/>
<!-- 环形进度条的背景色 -->
<attr name="circleBackgroundColor" format="color"/>
<!-- 进度条的颜色 -->
<attr name="progressColor" format="color"/>
<!-- 进度条的宽度 -->
<attr name="circleWidth" format="dimension"/>
<!-- 显示进度文本 -->
<attr name="showProgressText" format="boolean"/>
<!-- 进度文本的颜色 -->
<attr name="progressTextColor" format="color"/>
<!-- 进度文本的大小 -->
<attr name="progressTextSize"