环形进度条在开发中用的也不算少。今天来手动撸一个。
首先,定义一个 CircleProgressView,继承自View:
import android.animation.ValueAnimator;
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.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.yikelive.R;
import androidx.annotation.Nullable;
/**
* 普通环形进度条
*/
public class CircleProgressView extends View {
/**
* 当前进度
*/
private int mCurrent;
/**
* 背景弧线paint
*/
private Paint mBgPaint;
/**
* 进度Paint
*/
private Paint mProgressPaint;
/**
* 进度条宽度
*/
private float mProgressWidth;
/**
* 进度条颜色
*/
private int mProgressColor = Color.RED;
/**
* 开始角度
*/
private float startAngle;
private final RectF rectF = new RectF();
private ValueAnimator mAnimator;
private int max = 0;
public CircleProgressView(Context context) {
this(context, null);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
//起始位置
startAngle = typedArray.getInt(R.styleable.CircleProgressView_location_start, 1);
mProgressWidth = typedArray.getDimension(R.styleable.CircleProgressView_progress_width, dp2px(context, 4));
mProgressColor = typedArray.getColor(R.styleable.CircleProgressView_progress_color, mProgressColor);
typedArray.recycle();
//背景圆弧
mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setStrokeWidth(mProgressWidth);
mBgPaint.setStyle(Paint.Style.STROKE);
mBgPaint.setColor(Color.parseColor("#888888"));
mBgPaint.setStrokeCap(Paint.Cap.ROUND);
//进度圆弧
mProgressPaint = new Paint();
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStyle(Paint.Style.STROKE);
mProgressPaint.setStrokeWidth(mProgressWidth);
mProgressPaint.setColor(mProgressColor);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(width, height);
setMeasuredDimension(
MeasureSpec.makeMeasureSpec(size, MeasureSpec.getMode(widthMeasureSpec)),
MeasureSpec.makeMeasureSpec(size, MeasureSpec.getMode(heightMeasureSpec))
);
// 圆弧尺寸
rectF.set(mProgressWidth / 2,
mProgressWidth / 2,
width - mProgressWidth / 2,
height - mProgressWidth / 2);
}
/**
* oval // 绘制范围
* startAngle // 开始角度
* sweepAngle // 扫过角度
* useCenter // 是否使用中心
*/
@Override
protected void onDraw(Canvas canvas) {
//绘制背景圆弧
canvas.drawArc(rectF, 0, 360, false, mBgPaint);
//绘制当前进度
float sweepAngle = 360 * mCurrent / max;
canvas.drawArc(rectF, startAngle, sweepAngle, false, mProgressPaint);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
destroy();
}
public void setMax(int max) {
this.max = max;
}
public int getCurrent() {
return mCurrent;
}
/**
* 设置进度
*
* @param current
*/
public void setCurrent(int current) {
mCurrent = current;
invalidate();
}
private int tCurrent = -1;
/**
* 动画效果
*
* @param current 精度条进度:0-100
* @param duration 动画时间
*/
public void startAnimProgress(int current, int duration) {
mAnimator = ValueAnimator.ofInt(0, current);
mAnimator.setDuration(duration);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(animation -> {
int current1 = (int) animation.getAnimatedValue();
if (tCurrent != current1) {
tCurrent = current1;
setCurrent(current1);
if (mOnAnimProgressListener != null) {
mOnAnimProgressListener.valueUpdate(current1);
}
}
});
mAnimator.start();
}
public interface OnAnimProgressListener {
void valueUpdate(int progress);
}
private OnAnimProgressListener mOnAnimProgressListener;
/**
* 监听进度条进度
*
* @param onAnimProgressListener
*/
public void setOnAnimProgressListener(OnAnimProgressListener onAnimProgressListener) {
mOnAnimProgressListener = onAnimProgressListener;
}
public void destroy() {
if (mAnimator != null) {
mAnimator.cancel();
}
}
public static int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
进度条的View就算完了。说下使用方法
属性 | 释义 |
---|---|
progress_color | 进度条进度颜色 |
progress_width | 进度条宽度 |
progress.setMax(int size) | 设置总进度值 |
progress.setCurrent(int current) | 设置当前进度值 |
至于进度条的默认颜色(弧线默认颜色),可直接在代码中设置:
mBgPaint.setColor(Color.parseColor("#888888"));
到此。进度条就算完成了。
END