继上一篇《Android自定义View-NumberProgress》绘制了一个长型的数字进度条之后,这篇是自定义一个圆形的数字进度条。
老规矩,上效果图:
分析
这个控件主要由3部分构成,第一部分为未绘制进度的部分,第二部为绘制进度的部分,最后是中间的文字部分
实现
这个实现和上一篇文章类似,具体我就不啰嗦了
自定义的属性
获取自定义的属性
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.NumberProgress);
textColor = a.getColor(R.styleable.NumberProgress_textColor, Color.parseColor("#3498DB"));
textSize = sp2px(context, a.getDimension(R.styleable.NumberProgress_textSize, 14f));
unProgressColor = a.getColor(R.styleable.NumberProgress_unProgressColor, Color.parseColor("#113498DB"));
progressColor = a.getColor(R.styleable.NumberProgress_progressColor, Color.parseColor("#3498DB"));
currentProgress = a.getInt(R.styleable.NumberProgress_currentProgress, 0);
maxProgress = a.getInt(R.styleable.NumberProgress_maxProgress, 100);
arcWidth = dip2px(context,a.getDimension(R.styleable.NumberProgress_progressWidth,4));
3. 计算控件的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int widthMeasureSpec) {
int result;
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
int padding = getPaddingTop()+getPaddingBottom();
if (mode == MeasureSpec.EXACTLY){
result = size;
}else{
result = getSuggestedMinimumHeight();
result += padding;
if (mode == MeasureSpec.AT_MOST){
result = Math.max(result, size);
}
}
return result;
}
@Override
protected int getSuggestedMinimumWidth() {
return (int) dip2px(getContext(),100);
}
@Override
protected int getSuggestedMinimumHeight() {
return (int) dip2px(getContext(),100);
}
4. 计算图形大小以及位置
- 需要绘制的东西
1、未绘制的进度条就是一个空心的圆
2、绘制的进度条是一个弧
3、中间的文字
drawCircle(float cx, float cy, float radius,Paint paint)
// 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是画笔
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
//画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,
//参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象;
drawText(String text, float x, floaty, Paint paint)
//渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。
- 首先,我们确定空心的圆的圆心和半径
// 绘制浅色圆环
// 1.圆心(x,y)坐标值
float centerX = (getWidth()-getPaddingLeft()-getPaddingRight())/2.0f;
float centerY = (getHeight() - getPaddingTop() - getPaddingBottom())/2.0f;
// 2.圆环半径
float radius;
if (getWidth() >= getHeight()) {
radius = (centerY - arcWidth / 2);
}else{
radius = (centerX - arcWidth / 2);
}
canvas.drawCircle(centerX,centerY,radius,circlePaint);
- 绘制弧
绘制弧度需要一个RectF对象,就是限定弧度形状、大小;
弧度为0到当前进度除以100乘以一圈的度数360,这里这个RectF对象的大小就是圆心加减半径:
oval.left = centerX - radius;
oval.right = centerX + radius;
oval.top = centerY - radius;
oval.bottom = centerY+radius;
canvas.drawArc(oval, 0, (float)360 * currentProgress / (float)maxProgress, false, arcPaint);
- 绘制文字
绘制文字比较简单就不说了,直接上代码
currentDrawText = String.format("%d", currentProgress * 100 /maxProgress);
currentDrawText = (currentDrawText)+"%";
float drawTextWidth = textPaint.measureText(currentDrawText);
canvas.drawText(currentDrawText,centerX-drawTextWidth/2.0f,centerY-((textPaint.descent() + textPaint.ascent()) / 2.0f),textPaint);
5. 测试
测试和上篇文章是一样的
再来一遍效果图
完整代码请移步github:https://github.com/823546371/NumberProgress
本文地址:http://www.jianshu.com/p/6312861363b6
尊重原创,转载请注明:From 晓峰残月(http://jwenfeng.com) 侵权必究!