前言
自定义圆形进度条
基本变量
//-----------基本公共变量----------
//默认布局大小
private int mDefaultSize;
//是否开启抗锯齿
private boolean mAntiAliasl;
//半径
private float mRadius;
//圆心点
private Point mCirclePoint;
//绘制区域
private RectF mRectF;
//绘制起始角度,绘制扫过角度
private float startAngle, sweepAngle;
//显示值的范围百分比
private float mPercent;
//-----------画笔变量----------
private Paint mHintPaint;
private int mHintPaintColor;
private int mHintPaintSize;
private String mHintText;
//画笔位置偏移量-->用于计算绘制的y
private float mHintPaintOffSet;
private Paint mValuePaint;
private int mValuePaintColor;
private float mValuePaintSize;
private float mValuePaintOffSet;
private Paint mUnitPaint;
private int mUnitPaintColor;
private String mUnitText;
private float mUnitPaintSize;
private float mUnitPaintOffSet;
private Paint mArcPaint;
private int mArcPaintColor;
//画笔宽度
private int mArcPaintStroke;
private Paint mBgArcPaint;
private int mBgArcPaintColor;
private float mBgArcPaintStroke;
onMeasure 测量View大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//布局大小测量,默认大小
setMeasuredDimension(measureValue(widthMeasureSpec, mDefaultSize),
measureValue(heightMeasureSpec, mDefaultSize));
}
private int measureValue(int measureSpec, int defaultSize) {
int result = defaultSize;
int specMode = View.MeasureSpec.getMode(measureSpec);
int specSize = View.MeasureSpec.getSize(measureSpec);
if (specMode == View.MeasureSpec.EXACTLY) {
result = specSize;
} else if (specMode == View.MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
return result;
}
onSizeChanged 进行View中所有值的计算
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//所有子布局中属性计算
//半径计算
mRadius = Math.min(w,h) / 2 - mArcPaintStroke * 2;
//圆形点计算
mCirclePoint.x = w / 2;
mCirclePoint.y = h / 2;
//圆弧绘制范围计算
mRectF.left = mCirclePoint.x - mRadius;
mRectF.top = mCirclePoint.y - mRadius;
mRectF.right = mCirclePoint.x + mRadius;
mRectF.bottom = mCirclePoint.y + mRadius;
//文字绘制位置计算 y绘制位置
mValuePaintOffSet = mCirclePoint.y + measureTextHeight(mValuePaint) / 2;
if (mHintText != null) {
mHintPaintOffSet = mCirclePoint.y - mRadius * 0.33f + measureTextHeight(mHintPaint) / 2;
}
if (mUnitText != null) {
mUnitPaintOffSet = mCirclePoint.y + mRadius * 0.33f + measureTextHeight(mUnitPaint) / 2;
}
}
drawText 绘制文字
private void drawText(Canvas canvas) {
canvas.drawText(String.valueOf((int) (mMaxValueText * mPercent)), mCirclePoint.x, mValuePaintOffSet, mValuePaint);
if (mHintText != null) {
canvas.drawText(mHintText, mCirclePoint.x, mHintPaintOffSet, mHintPaint);
}
if (mUnitText != null) {
canvas.drawText(mUnitText, mCirclePoint.x, mUnitPaintOffSet, mUnitPaint);
}
}
drawArc 绘制圆弧
private void drawArc(Canvas canvas) {
canvas.save();
float currAngle = sweepAngle * mPercent;
canvas.rotate(startAngle, mCirclePoint.x, mCirclePoint.y);
canvas.drawArc(mRectF, currAngle, sweepAngle - currAngle, false, mBgArcPaint);
canvas.drawArc(mRectF, 2, currAngle, false, mArcPaint);
canvas.restore();
}
执行绘制
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawText(canvas);
drawArc(canvas);
}
执行效果动画
public void startAnimator() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f, 0.5f, 0.8f);
valueAnimator.setDuration(3000);
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float index = (float) animation.getAnimatedValue();
mPercent = index;
invalidate();
}
});
valueAnimator.start();
}