DHealthyProgressView
-
类似健康指数的 齿轮进度条 给Paint设置setPathEffect 来实现进度的间隔化
具体效果
- 默认模式 每次都是重新开始绘制
-
开启连续模式 增加模式 beginContinue(true)
开启连续 beginContinue(true); - 基本思路
因为在让进度里面存在别的控件 比如 文本 比如 ImageView
就让整个自定义View实现RelativeLayout 然后根据当前View的长宽来绘制弧形
弧形分为底部全弧度 basePaint 画笔
上面的进度弧度 progressPaint 画笔
初始化 用basePaint 绘制一个底部的进度 100%的弧度
然后 给 新设置的progress加一个动画 跟着动画的过程 来用 progressPaint 来绘制弧度 invalidate()方法通知draw 更新界面 直到动画完成
代码也不多 就直接贴了
public class DHealthyProgressView extends RelativeLayout {
private static final String TAG = DHealthyProgressView.class.getName();
private Interpolator interpolator = new AccelerateDecelerateInterpolator();
private int dBaserPainterColor = Color.YELLOW;
private int progressColor = Color.WHITE;
private float min = 0;
private float begin = min;
private float max = 100;
private ValueAnimator valueAnimator;
private OnValueChangeListener valueChangeListener;
private float mValue;
private int duration = 1000;
private int progressStrokeWidth = 48;
private int paddingT;
private boolean isComplete;
private int dashWith = 5;
private int dashSpace = 8;
private Paint progressPaint;
private int outPadding;
private Paint basePaint;
private RectF baseCircle;
private RectF progressCircle;
private float baseStartAngle = 270f;
private float baseFinishAngle = 359.8f;
private float progressStartAngle = 270f;
private float plusAngle;
private int paddingR;
private int paddingL;
private int paddingB;
private boolean isContinue;
public DHealthyProgressView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DHealthyProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attributeSet, int defStyleAttr) {
setWillNotDraw(false);
TypedArray attributes = context.obtainStyledAttributes(attributeSet, R.styleable.DashedCircularProgress, defStyleAttr, 0);
//获取padding属性
paddingT = getPaddingTop();
paddingL = getPaddingLeft();
paddingR = getPaddingRight();
paddingB = getPaddingBottom();
paddingT = paddingT + progressStrokeWidth / 2;
paddingL = paddingL + progressStrokeWidth / 2;
paddingR = paddingR + progressStrokeWidth / 2;
paddingB = paddingB + progressStrokeWidth / 2;
Log.e(TAG, "padding " + paddingT);
initAttributes(attributes);
}
private void initAttributes(TypedArray attributes) {
dBaserPainterColor = attributes.getColor(R.styleable.DashedCircularProgress_base_color,
dBaserPainterColor);
progressColor = attributes.getColor(R.styleable.DashedCircularProgress_progress_color,
progressColor);
max = attributes.getFloat(R.styleable.DashedCircularProgress_max, max);
duration = attributes.getInt(R.styleable.DashedCircularProgress_duration, duration);
progressStrokeWidth = attributes.getDimensionPixelOffset(R.styleable.DashedCircularProgress_progress_stroke_width,
progressStrokeWidth);
initPainters();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e(TAG, "onMeasure");
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
Log.e(TAG, "onlayout");
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.e(TAG, "initRectF " + w + "<--->" + h);
initBaseRectF(h, w);
initProgressRectF(h, w);
}
private void initProgressRectF(int h, int w) {
progressCircle = new RectF();
progressCircle.set(paddingL, paddingT, w - paddingR, h - paddingB);
}
private void initBaseRectF(int h, int w) {
baseCircle = new RectF();
baseCircle.set(paddingL, paddingT, w - paddingR, h - paddingB);
}
private void initPainters() {
initBasePainter();
initProgressPainter();
initValueAnimator();
}
/**
* 初始化进度画笔
*/
private void initProgressPainter() {
progressPaint = new Paint();
progressPaint.setAntiAlias(true);
progressPaint.setStrokeWidth(progressStrokeWidth);
progressPaint.setColor(progressColor);
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace},
dashSpace));
}
/**
* 初始化 底层 画笔
*/
private void initBasePainter() {
basePaint = new Paint();
basePaint.setAntiAlias(true);
basePaint.setStrokeWidth(progressStrokeWidth);
basePaint.setColor(dBaserPainterColor);
basePaint.setStyle(Paint.Style.STROKE);
basePaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace},
dashSpace));
}
/**
* 进度显示动画效果初始化
*/
private void initValueAnimator() {
valueAnimator = new ValueAnimator();
valueAnimator.setInterpolator(interpolator);
valueAnimator.addUpdateListener(new ValueAnimatorListenerImp());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e(TAG, "onDraw");
canvas.drawArc(baseCircle, baseStartAngle, baseFinishAngle, false, basePaint);
canvas.drawArc(progressCircle, progressStartAngle, plusAngle, false, progressPaint);
if (isComplete) {
return;
}
invalidate();
}
/**
* 设置进度值 重新开始绘制
*
* @param mValue
*/
public void setmValue(float mValue) {
if(this.mValue>=max){
Log.e(TAG,"最大值超出");
return;
}
if(isContinue){
this.mValue+=mValue;
}else {
begin=min;
this.mValue = mValue;
}
//最大值 最小值的限制
this.mValue=this.mValue>max?max:this.mValue;
this.mValue=this.mValue<min?min:this.mValue;
isComplete = false;
invalidate();
if (mValue <= max || mValue >= min) {
animateValue();
}
}
/**
* 属性动画开始
*/
private void animateValue() {
if (valueAnimator != null) {
valueAnimator.setFloatValues(begin, mValue);
valueAnimator.setDuration(duration);
valueAnimator.start();
}
}
public void setOnValueChangeListener(OnValueChangeListener valueChangeListener) {
this.valueChangeListener = valueChangeListener;
}
public void setInterpolator(Interpolator interpolator) {
this.interpolator = interpolator;
if (valueAnimator != null) {
valueAnimator.setInterpolator(interpolator);
}
}
public float getMin() {
return min;
}
public void setMin(float min) {
this.min = min;
}
public float getMax() {
return max;
}
public void setMax(float max) {
this.max = max;
}
/**
* 开启连续模式 每次在原有的进度上增加进度
* @param b
*/
public void beginContinue(boolean b) {
isContinue=b;
}
/**
* 动画开始 更新进度显示
*/
private class ValueAnimatorListenerImp implements ValueAnimator.AnimatorUpdateListener {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
Float value = (Float) valueAnimator.getAnimatedValue();
plusAngle = (baseFinishAngle * value) / max;
if (valueChangeListener != null) {
valueChangeListener.onValueChange(value);
}
begin = value;
if (begin == mValue) {
isComplete = true;
}
}
}
public interface OnValueChangeListener {
void onValueChange(float value);
}
public void reset() {
begin = min;
}
public int getProgressColor() {
return progressColor;
}
public void setProgressColor(int progressColor) {
this.progressColor = progressColor;
}
public int getdBaserPainterColor() {
return dBaserPainterColor;
}
public void setdBaserPainterColor(int dBaserPainterColor) {
this.dBaserPainterColor = dBaserPainterColor;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
valueAnimator.cancel();
}
}
网友评论