一:分析(背景、进度条、文字)
初始化需要的工具
private void init() {
//进度圆环
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));//笔刷颜色#3BB0E2
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(mCriWidth);//圆环宽度12
mCirclePaint.setStrokeCap(Paint.Cap.ROUND);//笔刷圆角
//文字描述
mTitlePaint = new Paint();
mTitlePaint.setAntiAlias(true);
mTitlePaint.setTextSize(mHumTitleSize);//字体大小20
mTitlePaint.setColor(Color.parseColor(mProgressBackGround));//字体颜色#3BB0E2
mTitlePaint.setStyle(Paint.Style.STROKE);
//背景图,将图片缩放到设置的宽度
mBackgroundBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.bg_nfc_progress), mWidth, mWidth, true);
}
二:测量画布宽高,调整圆半径、字体大小、线宽等
RxImageTool.sp2px,dp2px方法百度下都有
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int specSize = MeasureSpec.getSize(widthMeasureSpec);
// 参考宽,处理成正方形
setMeasuredDimension(specSize, specSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 控件宽、高
mWidth = Math.min(h, w);
//圆半径
mRadius = mWidth / 2 - mWidth / 200 * RxImageTool.dp2px(10);
//圆宽度
mCriWidth = mWidth / 200 * RxImageTool.sp2px(15);
//设置字体大小
mTitleSize = RxImageTool.sp2px(mWidth / 10);
//设置图片大小
mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap, mWidth, mWidth, true);
}
三:绘制看看
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//图片背景
canvas.drawBitmap(mBackgroundBitmap, 0, 0, mTitlePaint);
//画圆
drawCircle(canvas);
//画进度文字
drawTemText(canvas);
}
//画圆弧
private void drawCircle(Canvas canvas) {
canvas.save();
RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
//移至画布中心
canvas.translate(mWidth / 2, mWidth / 2);
//旋转角度,让起点从顶部开始
canvas.rotate(-90);
//画进度条,currentAnimationValue需根据进度条计算
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawArc(rectF, 0,currentAnimationValue, false, mCirclePaint);
canvas.restore();
}
// 画标题
private void drawTemText(Canvas canvas) {
canvas.save();
canvas.translate(mWidth / 2, mWidth / 2);
mTitlePaint.setTextSize(mHumTitleSize);
mHumTitle = mProgress + "%";
float humValue = mTitlePaint.measureText(mHumTitle);
mTitlePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawText(mHumTitle, -humValue / 2, RxImageTool.dp2px(7), mTitlePaint);
}
currentAnimationValue的计算方法
//计算1%进度对应的角度
mAngleOneHum = (float) 360 / (mMaxProgress - mMinProgress);
//根据当前进度计算需要绘制的角度
currentAnimationValue=mAngleOneHum * mProgress;
四:扩展功能
例设置进度、添加动画
//设置最大、最小、进度
public CircleProgressView setData(int minHum, int maxHum, int progress) {
this.mMinProgress = minHum;
this.mMaxProgress = maxHum;
if (progress < minHum) {
this.mProgress = minHum;
} else if (progress > maxHum) {
this.mProgress = maxHum;
} else {
this.mProgress = progress;
}
mAngleOneHum = (float) 360 / (mMaxProgress - mMinProgress);
return this;
}
//设置当前进度
public CircleProgressView setProgress(int progress) {
setData(mMinProgress, mMaxProgress, progress);
currentAnimationValue=mAngleOneHum * mProgress;
invalidate();
// setAnimation(currentAnimationValue,mAngleOneHum * mProgress,1000);
return this;
}
public int getProgress() {
return mProgress;
}
/**
* 为进度设置动画
* @param last
* @param current
*/
private void setAnimation(float last, float current, int duration) {
if(progressAnim !=null&& progressAnim.isRunning()){
progressAnim.cancel();
// isAnimation =true;
}
progressAnim = ValueAnimator.ofFloat(last, current);
progressAnim.setDuration(duration);
progressAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAnimationValue = (float) animation.getAnimatedValue();
invalidate();
}
});
progressAnim.addListener(new Animator.AnimatorListener(){
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// isAnimation =false;
}
@Override
public void onAnimationCancel(Animator animation) {
// isAnimation =false;
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
progressAnim.start();
}
完整代码
/**
* urkay
* 2020/5/12
* 圆形进度条
*/
public class CircleProgressView extends View {
//控件宽
private int mWidth = 200;
//半径
private int mRadius;
//字体宽度
private int mTitleSize;
// 圆环宽度
private int mCriWidth = RxImageTool.dp2px(12);
//文字大小
private int mHumTitleSize = RxImageTool.sp2px(20);
//圆笔触
private Paint mCirclePaint;
//当前进度笔触
private Paint mValueCirclePaint;
private Paint mTitlePaint;
//圆背景色
private String mCircleBackground = "#666666";
//圆进度色
private String mProgressBackGround = "#3BB0E2";
//最小进度
private int mMinProgress = 0;
//最大进度
private int mMaxProgress = 100;
//当前进度
private int mProgress = 50;
//标题
private String mHumTitle = "0%";
//当前进度每份的角度
private float mAngleOneHum = (float) 360 / (mMaxProgress - mMinProgress);
private Bitmap mBackgroundBitmap;
private ValueAnimator progressAnim;
private float currentAnimationValue;
public CircleProgressView(Context context) {
super(context);
init();
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
//进度圆环
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(Color.parseColor(mCircleBackground));
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(mCriWidth);
mCirclePaint.setStrokeCap(Paint.Cap.ROUND);//笔刷圆角
//文字描述
mTitlePaint = new Paint();
mTitlePaint.setAntiAlias(true);
mTitlePaint.setTextSize(mHumTitleSize);
mTitlePaint.setColor(Color.parseColor(mProgressBackGround));
mTitlePaint.setStyle(Paint.Style.STROKE);
//背景图
mBackgroundBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.bg_nfc_progress), mWidth, mWidth, true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int specSize = MeasureSpec.getSize(widthMeasureSpec);
// 参考宽,处理成正方形
setMeasuredDimension(specSize, specSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 控件宽、高
mWidth = Math.min(h, w);
//圆半径
mRadius = mWidth / 2 - mWidth / 200 * RxImageTool.dp2px(10);
//圆宽度
mCriWidth = mWidth / 200 * RxImageTool.sp2px(15);
//设置字体大小
mTitleSize = RxImageTool.sp2px(mWidth / 10);
//设置图片大小
mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap, mWidth, mWidth, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//图片背景
canvas.drawBitmap(mBackgroundBitmap, 0, 0, mTitlePaint);
//画圆
drawCircle(canvas);
//画进度文字
drawTemText(canvas);
}
//画圆弧
private void drawCircle(Canvas canvas) {
canvas.save();
RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
canvas.translate(mWidth / 2, mWidth / 2);
canvas.rotate(-90);
//画背景
// mCirclePaint.setColor(Color.parseColor(mCircleBackground));
// canvas.drawArc(rectF, 0, 361, false, mCirclePaint);
//画前景
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawArc(rectF, 0,currentAnimationValue, false, mCirclePaint);
canvas.restore();
}
// 画标题
private void drawTemText(Canvas canvas) {
canvas.save();
canvas.translate(mWidth / 2, mWidth / 2);
mTitlePaint.setTextSize(mHumTitleSize);
mHumTitle = mProgress + "%";
float humValue = mTitlePaint.measureText(mHumTitle);
mTitlePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawText(mHumTitle, -humValue / 2, RxImageTool.dp2px(7), mTitlePaint);
}
//设置最大、最小、进度
public CircleProgressView setData(int minHum, int maxHum, int progress) {
this.mMinProgress = minHum;
this.mMaxProgress = maxHum;
if (progress < minHum) {
this.mProgress = minHum;
} else if (progress > maxHum) {
this.mProgress = maxHum;
} else {
this.mProgress = progress;
}
mAngleOneHum = (float) 360 / (mMaxProgress - mMinProgress);
return this;
}
//设置当前进度
public CircleProgressView setProgress(int progress) {
setData(mMinProgress, mMaxProgress, progress);
currentAnimationValue=mAngleOneHum * mProgress;
invalidate();
// setAnimation(currentAnimationValue,mAngleOneHum * mProgress,1000);
return this;
}
public int getProgress() {
return mProgress;
}
/**
* 为进度设置动画
* @param last
* @param current
*/
private void setAnimation(float last, float current, int duration) {
if(progressAnim !=null&& progressAnim.isRunning()){
progressAnim.cancel();
// isAnimation =true;
}
progressAnim = ValueAnimator.ofFloat(last, current);
progressAnim.setDuration(duration);
progressAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentAnimationValue = (float) animation.getAnimatedValue();
invalidate();
}
});
progressAnim.addListener(new Animator.AnimatorListener(){
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// isAnimation =false;
}
@Override
public void onAnimationCancel(Animator animation) {
// isAnimation =false;
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
progressAnim.start();
}
@Override
protected void onAttachedToWindow() {
setAnimation(currentAnimationValue,mAngleOneHum * mProgress,1000);
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
if(progressAnim !=null&& progressAnim.isRunning()){
progressAnim.cancel();
}
super.onDetachedFromWindow();
}
}
网友评论