GLDriver/mylibrary/src/main/java/com/arpa/mylibrary/weight/CircleBarView2.java
2024-04-30 17:15:59 +08:00

263 lines
8.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.arpa.mylibrary.weight;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import com.arpa.mylibrary.R;
/**
* @ClassName CircleBarView2
* @Author john
* @Date 2024/2/7 16:28
* @Description TODO
*/
public class CircleBarView2 extends View {
private Paint outPaint, innerPaint;
private Paint mTextPaint, mValueTextPaint, mUnitTextPaint;
private final RectF oval = new RectF();
//最大进度
private int max = 100;
//当前进度
private int progress = 0;
//文本内容
private String text = "";
//数值内容
private String valueText = "";
//单位内容
private String unitText = "";
// 圆弧颜色
private int roundColor = getContext().getColor(R.color.color_f25);
// 设置数值颜色
private int valueColor = getContext().getColor(R.color.color_f25);
//用于动画
private float nowPro = 0;
private ValueAnimator animator;
// 文字间距
private int textMargin;
// 圆弧宽度、半径和数值、小间距
private int roundWidth, radius, smallMargin;
// view的高度
private int height;
// 中心点
private final Point centerPoint = new Point();
// 测量文字的范围
private final Rect textRect = new Rect();
public CircleBarView2(Context context) {
this(context, null);
}
public CircleBarView2(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleBarView2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs);
}
public int getMax() {
return max;
}
public void setMax(int max) {
this.max = max;
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
if (progress != 0 && this.progress == progress) {
return;
}
if (animator != null && animator.isRunning()) {
animator.cancel();
}
animator = ValueAnimator.ofFloat(nowPro, progress);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(animation -> {
nowPro = (float) animation.getAnimatedValue();
CircleBarView2.this.progress = (int) nowPro;
valueText = String.valueOf(CircleBarView2.this.progress);
invalidate();
});
animator.start();
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getValueText() {
return valueText;
}
public void setValueText(String valueText) {
this.valueText = valueText;
}
public String getUnitText() {
return unitText;
}
public void setUnitText(String unitText) {
this.unitText = unitText;
}
public void setRoundColor(int roundColor) {
this.roundColor = roundColor;
invalidate();
}
public void setValueColor(int valueColor) {
this.valueColor = valueColor;
invalidate();
}
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleBarView);
// 文字间距
textMargin = dp2px(context, 5);
// 圆弧宽度
roundWidth = dp2px(context, 8);
// 半径
radius = dp2px(context, 92);
height = radius;
// 小间距
smallMargin = roundWidth / 2;
outPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
outPaint.setColor(context.getColor(R.color.color_f6));
outPaint.setStyle(Paint.Style.STROKE);
outPaint.setStrokeCap(Paint.Cap.ROUND);
outPaint.setStrokeWidth(roundWidth);
innerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
innerPaint.setColor(context.getColor(R.color.color_f15));
innerPaint.setStyle(Paint.Style.STROKE);
innerPaint.setStrokeCap(Paint.Cap.ROUND);
innerPaint.setStrokeWidth(roundWidth + 10);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(context.getColor(R.color.color_9));
mTextPaint.setTextSize(sp2px(getContext(), 16));
mValueTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mValueTextPaint.setColor(valueColor);
mValueTextPaint.setTextSize(sp2px(getContext(), 34));
mUnitTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mUnitTextPaint.setColor(context.getColor(R.color.color_ff3));
mUnitTextPaint.setTextSize(sp2px(getContext(), 12));
//动画
animator = ValueAnimator.ofFloat(0, progress);
animator.setDuration(1000);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(animation -> {
nowPro = (float) animation.getAnimatedValue();
postInvalidate();
});
animator.start();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, (int) height);
} else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, heightSpecSize);
height = heightSpecSize;
} else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSpecSize, (int) height);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 中心点
centerPoint.set(getWidth() / 2, height / 2);
// 计算圆弧显示的范围height * 2 是因为圆弧的高度是根据园来算的,所以双倍才是半个圆
oval.set(getWidth() / 2f - radius, (float) roundWidth, getWidth() / 2f + radius, height * 2 - roundWidth * 2);
}
@Override
protected void onDraw(Canvas canvas) {
// 最外层圆弧
canvas.drawArc(oval, 180, 180, false, outPaint); //绘制外层圆弧
// 进度圆弧
if (nowPro > 0) {
innerPaint.setColor(roundColor);
} else {
innerPaint.setColor(getContext().getColor(R.color.color_f6));
}
canvas.drawArc(oval, 180, 180f * nowPro / max, false, innerPaint); //绘制圆弧
// 文字从底部从下往上绘制。
int valueY = height - smallMargin;
// 值
float valueTextWidth = mValueTextPaint.measureText(valueText);
float unitTextWidth = mUnitTextPaint.measureText(unitText);
canvas.drawText(valueText, centerPoint.x - (valueTextWidth + unitTextWidth) / 2f, valueY, mValueTextPaint);
// 单位
canvas.drawText(unitText, centerPoint.x + valueTextWidth / 2f - unitTextWidth / 2f + smallMargin, valueY, mUnitTextPaint);
// 测量值的高度
mValueTextPaint.getTextBounds(text, 0, text.length(), textRect);
// 提示文字("高血压")
float textWidth = mTextPaint.measureText(text);
// 文字的高度 = 值的高度起点 - 值的高度 - 间距
float textY = valueY - textRect.height() - textMargin;
canvas.drawText(text, centerPoint.x - textWidth / 2f, textY, mTextPaint);
}
/**
* dp 转 px
*/
private int dp2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* sp 转 px
*/
private int sp2px(Context context, float spValue) {
final float scale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * scale + 0.5f);
}
}