话不多说先上效果图
非常简单的一个圆环进度条 主要有以下主要功能
1.支持中间文字的显示隐藏,修改样式
2.支持自定义进度条背景的颜色宽度以及进度条的颜色宽度
3.支持开启关闭动画效果
4.支持自定义动画的插值器,动画时长
接下来我们就来一步步说下是如何实现这个小功能的:
分析:想要自定义view首先要了结自定义view的一些步骤和一些关键方法的含义
1.首先我们新建一个类 让这个类继承自View ,然后会提示我们要重写他的构造方法,这个时候我们选择实现它的三个构造函数并稍微改造一下让第一个方法调用第二个方法,第二个方法调用第三个构造函数 每个方法的含义我已经在方法体上加了注释 如下三个:
2.因为这个view最终的时候执行的是第三个构造函数,所以我们要在第三个构造函数里做一些我们初始化属性以及画笔 的一些操作
public RingProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
@SuppressLint({"Recycle", "CustomViewStyleable"})
//通过obtainStyledAttributes 获取typearrat
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RingProgressBar_style);
//下边是我们自定义的一些style属性
float backgroundWidth = typedArray.getDimension(R.styleable.RingProgressBar_style_barBackgroundWidth, 5);
int backgroundColor = typedArray.getColor(R.styleable.RingProgressBar_style_barBackgroundColor, Color.LTGRAY);
float barWidth = typedArray.getDimension(R.styleable.RingProgressBar_style_barProgressWidth, 5);
int barColor = typedArray.getColor(R.styleable.RingProgressBar_style_barColor, Color.BLUE);
int textColor = typedArray.getColor(R.styleable.RingProgressBar_style_progress_text_color, Color.BLACK);
float textSize = typedArray.getDimension(R.styleable.RingProgressBar_style_progress_text_size, 16);
progress = typedArray.getFloat(R.styleable.RingProgressBar_style_progress, 0);
isShowText = typedArray.getBoolean(R.styleable.RingProgressBar_style_isShowText, false);
EnableAnimation = typedArray.getBoolean(R.styleable.RingProgressBar_style_EnableAnimation, false);
durationTime = typedArray.getInteger(R.styleable.RingProgressBar_style_durationTime, 2000);
// 初始化背景圆环画笔
backgroundPaint = initPaint(backgroundWidth, backgroundColor);
// 初始化进度圆环画笔
progressPaint = initPaint(barWidth, barColor);
// 初始化TestPaint
textPaint = new TextPaint();
textPaint.setColor(textColor);
textPaint.setTextSize(textSize);
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
//获取当前进度
typedArray.recycle();
}
private Paint initPaint(float width, int color) {
Paint paint = new Paint();
paint.setStrokeWidth(width);
paint.setColor(color);
paint.setAntiAlias(true); //抗锯齿
paint.setStyle(Paint.Style.STROKE); //充满
paint.setStrokeCap(Paint.Cap.ROUND);//圆角
paint.setDither(true); // 设置抖动
return paint;
}
3.接下来是最重要的环节了 重写onMeasure 方法 这个方法是用来测量view的大小
因为们要绘制的是一个圆形的进度条 势必要用到 canvas.drawArc()方法 这个方法 有两种方式画一个圆形,其实归根结底是一样的,传左上右下的位置其实也是一个RectF 所以这里我们直接再onMeasure 里边计算出RectF的值然后在onDraw方法中直接调用就好
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//计算View宽度
int widthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
//计算View高度
int heightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
//矩形的宽度 因为圆形是RectF这个矩形的内切圆 所以矩形的宽度不能和view的宽度一样宽,那样的话 加上圆环本身的线条宽度 势必会在矩形的四个中点位置显示不完全 所以要减去一个圆环本身的宽度 这里估计又有人该问了,为啥是减去一个圆环本身的宽度而不是两个 因为如果一个圆环的宽度是4 那么在圆环绘制在矩形之中,那么圆环与矩形相交的四个顶点 每一个顶点的位置刚好是在 4的中间 2的位置 所以圆环左右2个顶点会各会有一半越过矩形的边框 同理上下也是,所以我们只需要减去一个圆环的宽度就够了,如果这个时候我们的矩形宽度和view本身的一样 那么这四个顶点就会被切割显示不全,所以这里是这样计算的
int mRectLength = (int) (Math.max(widthSize, heightSize) - Math.max(backgroundPaint.getStrokeWidth(), progressPaint.getStrokeWidth()));
//左顶点的位置 widthSize - mRectLength 是一个圆环的宽度 除以2 半个圆环的宽度 刚好能把圆环显示出来
int leftPoint = getPaddingLeft() + (widthSize - mRectLength) / 2;
//左上角 同以上道理
int rightPoint = getPaddingTop() + (widthSize - mRectLength) / 2;
mRectF = new RectF(leftPoint, rightPoint, leftPoint + mRectLength, rightPoint + mRectLength);
}
4. 在第三步的时候我们已经计算出RectF的位置了 所以在此我们可以轻松的画出一个圆形
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "onDraw: ");
//绘制背景
canvas.drawArc(mRectF, 0, 360, false, backgroundPaint);
if (progress > 100) {
progress = 100;
}
if (isShowText) {
//绘制文字
String progressText = (int) progress + "%";
Rect bounds = new Rect();
textPaint.getTextBounds(progressText, 0, progressText.length(), bounds);
//计算出文字y轴的偏移量。 文字整体的高度除以2
float offset = (bounds.top + bounds.bottom) / 2;
canvas.drawText(progressText, mRectF.centerX(), mRectF.centerY() - offset, textPaint);
}
//绘制进度
canvas.drawArc(mRectF, 270, 360 * progress / 100, false, progressPaint);
}
好了,以上基本就是圆环进度条主要的实现步骤了。源码我已经上传 https://download.csdn.net/download/APPLYB/13195601不懂的可以去看下源码 直接拷贝到项目里就能用了