需求背景:
畫一個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 = -;
private float strokeWidth = ;
private float background = ;
private float progressBackground = ;
private float progress = ;
private float secondProgress = ;
private int min = ;
private int max = ;
public CircleProgressBar(Context context) {
this(context, null);
}
public CircleProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, );
}
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,
, );
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) ));
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 = * progressBackground / max;
float angleMiddle = * secondProgress / max;
float angleFore = * (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( + strokeWidth / , + strokeWidth / , min - strokeWidth / , min - strokeWidth - );
}
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();
objectAnimator.setInterpolator(new DecelerateInterpolator());
animator1 = objectAnimator;
// objectAnimator.start();
}
public void setSecondProgressWithAnimation(float progress) {
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "secondProgress", progress);
objectAnimator.setDuration();
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();
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();
circle_bar.setSecondProgressWithAnimation();
circle_bar.setProgressWithAnimation();