需求背景:
画一个app占用的内存图,其中有三个弧,
1、背景全部内存的圈圈;
2、本app占用的内存
3、除app外其他文件占用的大小
进来查看缓存图时,环形需要动态显示
技术分析:
从图上看,挺简单的,就三条圆弧,笔宽如图这么大就可以了;
设置三个Paint的不同颜色;
计算所占的比例;
重点以前不懂动态显示圆弧;
网上查阅:
主要是利用ObjectAnimator 的ofFloat效果
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress",progress)
//progress 的getter和setter
View的代码如下:
package com.github.azhansy.timepickdemo;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
/**
* Created by zhanshuyong on 2017/3/10.
* 动态的圆环圈
*/
public class CircleProgressBar extends View {
private RectF rectF;
private Paint initPaint;
private Paint backgroundPaint;
private Paint foregroundPaint;
private Paint middlePaint;
private Paint ratesign;
private int backgroundColor = Color.parseColor("#999999");
private int middleColor = Color.parseColor("#00a8ff");
private int foregroundColor = Color.parseColor("#3F51B5");
/**
* 进度条以90度角起始(12点方向)
*/
private int startAngle = -90;
private float strokeWidth = 74;
private float background = 0;
private float progressBackground = 0;
private float progress = 0;
private float secondProgress = 0;
private int min = 0;
private int max = 100;
public CircleProgressBar(Context context) {
this(context, null);
}
public CircleProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
intView(context, attrs, defStyleAttr);
}
private void intView(Context context, AttributeSet attrs, int defStyleAttr) {
rectF = new RectF();
TypedArray typedArray = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.CircleProgressBar,
0, 0);
try {
strokeWidth = typedArray.getDimension(R.styleable.CircleProgressBar_progressBarThickness, strokeWidth);
progress = typedArray.getFloat(R.styleable.CircleProgressBar_progress, progress);
secondProgress = typedArray.getFloat(R.styleable.CircleProgressBar_secondProgress, secondProgress);
foregroundColor = typedArray.getInt(R.styleable.CircleProgressBar_progressbarColor, foregroundColor);
middleColor = typedArray.getInt(R.styleable.CircleProgressBar_secondProgressbarColor, middleColor);
backgroundColor = typedArray.getInt(R.styleable.CircleProgressBar_progressBarBackgroundColor, backgroundColor);
min = typedArray.getInt(R.styleable.CircleProgressBar_min, min);
max = typedArray.getInt(R.styleable.CircleProgressBar_max, max);
} finally {
typedArray.recycle();
}
ratesign = new Paint(Paint.ANTI_ALIAS_FLAG);
ratesign.setColor(ContextCompat.getColor(getContext(), R.color.progress_rate));
ratesign.setTextSize(sp2px((float) 17));
initPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
initPaint.setColor(Color.TRANSPARENT);
initPaint.setStyle(Paint.Style.STROKE);
initPaint.setStrokeWidth(strokeWidth);
backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
backgroundPaint.setColor(backgroundColor);
backgroundPaint.setStyle(Paint.Style.STROKE);
backgroundPaint.setStrokeWidth(strokeWidth);
foregroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
foregroundPaint.setColor(foregroundColor);
foregroundPaint.setStyle(Paint.Style.STROKE);
foregroundPaint.setStrokeWidth(strokeWidth);
middlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
middlePaint.setColor(middleColor);
middlePaint.setStyle(Paint.Style.STROKE);
middlePaint.setStrokeWidth(strokeWidth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawOval(rectF, initPaint);
float angleBack = 360 * progressBackground / max;
float angleMiddle = 360 * secondProgress / max;
float angleFore = 360 * (progress + secondProgress) / max;
canvas.drawArc(rectF, startAngle, angleBack, false, backgroundPaint);
canvas.drawArc(rectF, startAngle, angleFore, false, foregroundPaint);
canvas.drawArc(rectF, startAngle, angleMiddle, false, middlePaint);
// canvas.drawText(secondProgress + "%", rectF.centerX(), rectF.centerY(), ratesign);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
int min = Math.min(width, height);
setMeasuredDimension(min, min);
rectF.set(0 + strokeWidth / 2, 0 + strokeWidth / 2, min - strokeWidth / 2, min - strokeWidth - 2);
}
private ObjectAnimator animator1, animator2;
public void setProgress(float progress) {
this.progress = progress;
invalidate();
}
public float getSecondProgress() {
return secondProgress;
}
public void setSecondProgress(float secondProgress) {
this.secondProgress = secondProgress;
invalidate();
}
public float getProgressBackground() {
return progressBackground;
}
public void setProgressBackground(float progressBackground) {
this.progressBackground = progressBackground;
invalidate();
}
public float getProgress() {
return progress;
}
public void setMax(int max) {
this.max = max;
invalidate();
}
public void setBackgroundProgressColor(int color) {
this.backgroundColor = color;
backgroundPaint.setColor(color);
invalidate();
requestLayout();
}
public void setMiddleProgessColor(int color) {
this.middleColor = color;
middlePaint.setColor(color);
invalidate();
requestLayout();
}
public void setForegroundProgessColor(int color) {
this.foregroundColor = color;
foregroundPaint.setColor(color);
invalidate();
requestLayout();
}
/**
* Set the progress with an animation.
* Note that the {@link ObjectAnimator} Class automatically set the progress
* so don't call the {@link CircleProgressBar#setProgress(float)} directly within this method.
*
* @param progress The progress it should animate to it.
*/
public void setProgressWithAnimation(float progress) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress", progress);
objectAnimator.setDuration(500);
objectAnimator.setInterpolator(new DecelerateInterpolator());
animator1 = objectAnimator;
// objectAnimator.start();
}
public void setSecondProgressWithAnimation(float progress) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "secondProgress", progress);
objectAnimator.setDuration(500);
objectAnimator.setInterpolator(new DecelerateInterpolator());
animator2 = objectAnimator;
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (animator1 != null) {
animator1.start();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
// objectAnimator.start();
}
public void setProgressBackgroundWithAnimation(float progress) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progressBackground", progress);
objectAnimator.setDuration(1000);
objectAnimator.setInterpolator(new DecelerateInterpolator());
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (animator2 != null) {
animator2.start();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
objectAnimator.start();
}
private float sp2px(Float sp) {
float scaleDensity = getContext().getResources().getDisplayMetrics().scaledDensity;
return sp * scaleDensity;
}
}
调用方法:
CircleProgressBar circle_bar = (CircleProgressBar) findViewById(R.id.circle_bar);
circle_bar.setProgressBackgroundWithAnimation(100);
circle_bar.setSecondProgressWithAnimation(10);
circle_bar.setProgressWithAnimation(30);