需求背景: 画一个app占用的内存图,其中有三个弧, 1、背景全部内存的圈圈; 2、本app占用的内存 3、除app外其他文件占用的大小 进来查看缓存图时,环形需要动态显示 技术分析: 从图上看,挺简单的,就三条圆弧,笔宽如图这么大就可以了; 设置三个Paint的不同颜色; 计算所占的比例; 重点以前不懂动态显示圆弧; 网上查阅: 主要是利用ObjectAnimator 的ofFloat效果
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress",progress) //progress 的getter和setterView的代码如下:
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);