效果圖
背景圖.png
一:分析(背景玩祟、進(jìn)度條港准、文字)
初始化需要的工具
private void init() {
//進(jìn)度圓環(huán)
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));//筆刷顏色#3BB0E2
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(mCriWidth);//圓環(huán)寬度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);
//背景圖,將圖片縮放到設(shè)置的寬度
mBackgroundBitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.bg_nfc_progress), mWidth, mWidth, true);
}
二:測(cè)量畫(huà)布寬高抄瑟,調(diào)整圓半徑凡泣、字體大小、線寬等
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);
//設(shè)置字體大小
mTitleSize = RxImageTool.sp2px(mWidth / 10);
//設(shè)置圖片大小
mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap, mWidth, mWidth, true);
}
三:繪制看看
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//圖片背景
canvas.drawBitmap(mBackgroundBitmap, 0, 0, mTitlePaint);
//畫(huà)圓
drawCircle(canvas);
//畫(huà)進(jìn)度文字
drawTemText(canvas);
}
//畫(huà)圓弧
private void drawCircle(Canvas canvas) {
canvas.save();
RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
//移至畫(huà)布中心
canvas.translate(mWidth / 2, mWidth / 2);
//旋轉(zhuǎn)角度惹资,讓起點(diǎn)從頂部開(kāi)始
canvas.rotate(-90);
//畫(huà)進(jìn)度條贺纲,currentAnimationValue需根據(jù)進(jìn)度條計(jì)算
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawArc(rectF, 0,currentAnimationValue, false, mCirclePaint);
canvas.restore();
}
// 畫(huà)標(biāo)題
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的計(jì)算方法
//計(jì)算1%進(jìn)度對(duì)應(yīng)的角度
mAngleOneHum = (float) 360 / (mMaxProgress - mMinProgress);
//根據(jù)當(dāng)前進(jìn)度計(jì)算需要繪制的角度
currentAnimationValue=mAngleOneHum * mProgress;
四:擴(kuò)展功能
例設(shè)置進(jìn)度、添加動(dòng)畫(huà)
//設(shè)置最大褪测、最小猴誊、進(jìn)度
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;
}
//設(shè)置當(dāng)前進(jìn)度
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;
}
/**
* 為進(jìn)度設(shè)置動(dòng)畫(huà)
* @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
* 圓形進(jìn)度條
*/
public class CircleProgressView extends View {
//控件寬
private int mWidth = 200;
//半徑
private int mRadius;
//字體寬度
private int mTitleSize;
// 圓環(huán)寬度
private int mCriWidth = RxImageTool.dp2px(12);
//文字大小
private int mHumTitleSize = RxImageTool.sp2px(20);
//圓筆觸
private Paint mCirclePaint;
//當(dāng)前進(jìn)度筆觸
private Paint mValueCirclePaint;
private Paint mTitlePaint;
//圓背景色
private String mCircleBackground = "#666666";
//圓進(jìn)度色
private String mProgressBackGround = "#3BB0E2";
//最小進(jìn)度
private int mMinProgress = 0;
//最大進(jìn)度
private int mMaxProgress = 100;
//當(dāng)前進(jìn)度
private int mProgress = 50;
//標(biāo)題
private String mHumTitle = "0%";
//當(dāng)前進(jìn)度每份的角度
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() {
//進(jìn)度圓環(huán)
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);
//設(shè)置字體大小
mTitleSize = RxImageTool.sp2px(mWidth / 10);
//設(shè)置圖片大小
mBackgroundBitmap = Bitmap.createScaledBitmap(mBackgroundBitmap, mWidth, mWidth, true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//圖片背景
canvas.drawBitmap(mBackgroundBitmap, 0, 0, mTitlePaint);
//畫(huà)圓
drawCircle(canvas);
//畫(huà)進(jìn)度文字
drawTemText(canvas);
}
//畫(huà)圓弧
private void drawCircle(Canvas canvas) {
canvas.save();
RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
canvas.translate(mWidth / 2, mWidth / 2);
canvas.rotate(-90);
//畫(huà)背景
// mCirclePaint.setColor(Color.parseColor(mCircleBackground));
// canvas.drawArc(rectF, 0, 361, false, mCirclePaint);
//畫(huà)前景
mCirclePaint.setColor(Color.parseColor(mProgressBackGround));
canvas.drawArc(rectF, 0,currentAnimationValue, false, mCirclePaint);
canvas.restore();
}
// 畫(huà)標(biāo)題
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);
}
//設(shè)置最大稠肘、最小、進(jìn)度
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;
}
//設(shè)置當(dāng)前進(jìn)度
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;
}
/**
* 為進(jìn)度設(shè)置動(dòng)畫(huà)
* @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();
}
}