继上一篇《Android自定义View-NumberProgress》绘制了一个长型的数字进度条之后,这篇是自定义一个圆形的数字进度条。 老规矩,上效果图:
这个控件主要由3部分构成,第一部分为未绘制进度的部分,第二部为绘制进度的部分,最后是中间的文字部分
这个实现和上一篇文章类似,具体我就不啰嗦了
<?xmlversion="1.0" encoding="utf-8"?> <resources> <declare-styleablename="NumberProgress"> <!-- 文字大小 --> <attrname="textSize" format="dimension"/> <!-- 文字颜色 --> <attrname="textColor" format="color"/> <!-- reached的高度 --> <attrname="reachedHeight" format="dimension"/> <!-- reached的颜色 --> <attrname="reachedColor" format="color"/> <!-- unReached的高度 --> <attrname="unReachedHeight" format="dimension"/> <!-- unReached的颜色 --> <attrname="unReachedColor" format="color"/> <!-- 当前进度 --> <attrname="currentProgress" format="integer"/> <!-- 总进度 --> <attrname="maxProgress" format="integer"/> <!-- unProgress颜色 --> <attrname="unProgressColor" format="color"/> <!-- progress颜色 --> <attrname="progressColor" format="color"/> <!-- progress宽度 --> <attrname="progressWidth" format="dimension"/> </declare-styleable> </resources>
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));
@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); }
drawCircle(float cx, float cy, float radius,Paintpaint) // 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是画笔 drawArc(RectFoval, float startAngle, float sweepAngle, boolean useCenter, Paintpaint) //画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始, //参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象; drawText(String text, float x, floaty, Paintpaint) //渲染文本,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);
测试和上篇文章是一样的 再来一遍效果图