Android中圆形进度条的应用还是挺多的,最近学习实现了圆形进度条。
思路
要实现圆形进度条,
首先要画灰色背景圆环
再画蓝色进度圆环
再画进度数字
搞定。
首先自定义各种属性
初始化各种属性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
textIsDisplayable = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
//资源回收
typedArray.recycle();
初始化三种画笔
//背景圆环画笔
ringPaint = new Paint();
ringPaint.setColor(ringColor);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(ringWidth);
ringPaint.setAntiAlias(true);
//进度圆环画笔
ringProgressPaint = new Paint();
ringProgressPaint.setColor(ringProgressColor);
ringProgressPaint.setStrokeWidth(ringWidth);
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
ringProgressPaint.setAntiAlias(true);
switch (style) {
case STROKE:
ringProgressPaint.setStyle(Paint.Style.STROKE);
break;
case FULL:
ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
break;
}
//进度文字画笔
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
抗锯齿
ringPaint.setAntiAlias(true);
圆形线条
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
圆环整体图
画背景圆环
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) (xCenter - ringWidth / 2);
canvas.drawCircle(xCenter, yCenter, radius, ringPaint);
xCenter:圆心横坐标
yCenter:圆心纵坐标
radius:半径
ringPaint:画笔
疑惑
这里我有点疑惑,为什么半径是xCenter - ringWidth / 2呢?
我认为半径应该是xCenter - ringWidth才对,很合理,宽度的一半减去线条宽度,刚好是圆环的半径。
怀着疑惑的心情画了上图,这里减去圆环线条宽度的一半或许是因为线条的宽度不可忽略,姑且这样认为吧,如果有大神看到希望指点迷津。
画进度圆环
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
switch (style) {
case STROKE:
/*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
break;
case FULL:
if (progress != 0) {
canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
}
break;
}
左上右下
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
xCenter - radius:矩形距离左边的距离
yCenter - radius:矩形距离上边的距离
xCenter + radius:矩形距离右边的距离
yCenter + radius:矩形距离下边的距离
其实可以理解为矩形左上角的坐标和右下角的坐标
画圆弧
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
rectF:圆弧在这个矩形中绘制
-90:圆弧顺时针绘制的开始角度
progress * 360 / max:圆弧绘制的角度
false:绘制时是否经过圆心,当style设置为STROKE时,是没有效果的,这里借用两张图片,简单明了
当style设置为FULL,这里设置为false时
当style设置为FULL,这里设置为true时
ringProgressPaint:画笔
魅族应用市场下载效果
canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);
将进度分两次绘制,从底部同时向上绘制进度的一半,就达到了这个效果。
画进度数字
String text = progress + "%";
float textWidth = textPaint.measureText(text, 0, text.length());
if (showTextProgress && progress != 0 && style == STROKE) {
canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
}
RingProgressBar
package com.goldou.ringprogressbar;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Administrator on 2017.10.30 0030.
*/
public class RingProgressBar extends View {
private Paint ringPaint;
private Paint ringProgressPaint;
private Paint textPaint;
private int ringColor;
private int ringProgressColor;
private int textColor;
private float textSize;
private float ringWidth;
private int max;
private int progress;
private boolean showTextProgress;
private int style;
private final int STROKE = 0;
private final int FULL = 1;
private Context context;
public RingProgressBar(Context context) {
this(context, null);
}
public RingProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RingProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
initAttrs(context, attrs);
initPaint();
}
private void initPaint() {
ringPaint = new Paint();
ringPaint.setColor(ringColor);
ringPaint.setStyle(Paint.Style.STROKE);
ringPaint.setStrokeWidth(ringWidth);
ringPaint.setAntiAlias(true);
ringProgressPaint = new Paint();
ringProgressPaint.setColor(ringProgressColor);
ringProgressPaint.setStrokeWidth(ringWidth);
ringProgressPaint.setStrokeCap(Paint.Cap.ROUND);
ringProgressPaint.setAntiAlias(true);
switch (style) {
case STROKE:
ringProgressPaint.setStyle(Paint.Style.STROKE);
break;
case FULL:
ringProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
break;
}
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar);
ringColor = typedArray.getColor(R.styleable.RingProgressBar_ringColor, Color.GRAY);
ringProgressColor = typedArray.getColor(R.styleable.RingProgressBar_ringProgressColor, Color.GREEN);
textColor = typedArray.getColor(R.styleable.RingProgressBar_textColor, Color.GREEN);
textSize = typedArray.getDimension(R.styleable.RingProgressBar_textSize, 16);
ringWidth = typedArray.getDimension(R.styleable.RingProgressBar_ringWidth, 5);
max = typedArray.getInteger(R.styleable.RingProgressBar_max, 100);
showTextProgress = typedArray.getBoolean(R.styleable.RingProgressBar_showTextProgress, true);
style = typedArray.getInt(R.styleable.RingProgressBar_style, 0);
//资源回收
typedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) (xCenter - ringWidth / 2);
canvas.drawCircle(xCenter, yCenter, radius, ringPaint);
RectF rectF = new RectF(xCenter - radius, yCenter - radius, xCenter + radius, yCenter + radius);
switch (style) {
case STROKE:
/*canvas.drawArc(rectF, 90, progress * 180 / max, false, ringProgressPaint);
canvas.drawArc(rectF, 90, -progress * 180 / max, false, ringProgressPaint);*/
canvas.drawArc(rectF, -90, progress * 360 / max, false, ringProgressPaint);
break;
case FULL:
if (progress != 0) {
canvas.drawArc(rectF, -90, progress * 360 / 100, true, ringProgressPaint);
}
break;
}
String text = progress + "%";
float textWidth = textPaint.measureText(text, 0, text.length());
if (showTextProgress && progress != 0 && style == STROKE) {
canvas.drawText(text, xCenter - textWidth / 2, yCenter + textSize / 2, textPaint);
}
}
public synchronized int getMax() {
return max;
}
public synchronized void setMax(int max) {
if (max < 0) {
throw new IllegalArgumentException("max not less than 0");
}
this.max = max;
}
public synchronized int getProgress() {
return progress;
}
public synchronized void setProgress(int progress) {
if (progress < 0) {
throw new IllegalArgumentException("progress not less than 0");
}
if (progress > max) {
progress = max;
}
if (progress <= max) {
this.progress = progress;
postInvalidate();
}
}
public int getRingColor() {
return ringColor;
}
public void setRingColor(int ringColor) {
this.ringColor = ringColor;
}
public int getRingProgressColor() {
return ringProgressColor;
}
public void setRingProgressColor(int ringProgressColor) {
this.ringProgressColor = ringProgressColor;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
public float getRingWidth() {
return ringWidth;
}
public void setRingWidth(float roundWidth) {
this.ringWidth = roundWidth;
}
}
最后
有什么解释不对还望各位大神指正