public class CircleProgressBar extends View {
private Paint mFirstPaint;
private Paint mSecondPaint;
private Context mContext;
private CircleInfo mFirstCircle;
private CircleInfo mSecondCircle;
private float mCenterX;
private float mCenterY;
private float mDistance = 50;
private static final float MAX_RADIUS = 60;
private static final float MIN_RADIUS = 15;
public CircleProgressBar(Context context) {
super(context);
init(context);
}
public CircleProgressBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CircleProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context){
mContext = context;
initPaint();
initCircle();
startProgressBarAnimator();
}
private void initPaint(){
mFirstPaint = new Paint();
mFirstPaint.setColor(Color.RED);
mFirstPaint.setStyle(Paint.Style.FILL);
mFirstPaint.setAntiAlias(true);
mSecondPaint = new Paint();
mSecondPaint.setColor(Color.BLUE);
mSecondPaint.setStyle(Paint.Style.FILL);
mSecondPaint.setAntiAlias(true);
}
private void initCircle(){
mFirstCircle = new CircleInfo();
mFirstCircle.setColor(Color.RED);
mSecondCircle = new CircleInfo();
mSecondCircle.setColor(Color.BLUE);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w / 2;
mCenterY = h / 2;
mFirstCircle.setCenter(mCenterX);
mSecondCircle.setCenter(mCenterX);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mFirstCircle.getRadius() > mSecondCircle.getRadius()) {
canvas.drawCircle(mSecondCircle.getCenter(), mCenterY, mSecondCircle.getRadius(), mSecondPaint);
canvas.drawCircle(mFirstCircle.getCenter(), mCenterY, mFirstCircle.getRadius(), mFirstPaint);
} else {
canvas.drawCircle(mFirstCircle.getCenter(), mCenterY, mFirstCircle.getRadius(), mFirstPaint);
canvas.drawCircle(mSecondCircle.getCenter(), mCenterY, mSecondCircle.getRadius(), mSecondPaint);
}
}
private void startProgressBarAnimator(){
ValueAnimator firstCenterXAnimation = ValueAnimator.ofFloat(-1, 0, 1, 0, -1);
firstCenterXAnimation.setRepeatCount(ValueAnimator.INFINITE);
firstCenterXAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float)animation.getAnimatedValue();
float centerX = mCenterX + mDistance * value;
mFirstCircle.setCenter(centerX);
invalidate();
}
});
ValueAnimator secondCenterXAnimation = ValueAnimator.ofFloat(1, 0, -1, 0, 1);
secondCenterXAnimation.setRepeatCount(ValueAnimator.INFINITE);
secondCenterXAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float)animation.getAnimatedValue();
float centerX = mCenterX + mDistance * value;
mSecondCircle.setCenter(centerX);
invalidate();
}
});
float middleRadius = (MAX_RADIUS + MIN_RADIUS) / 2;
ValueAnimator firstRadiusAnimation = ValueAnimator.ofFloat(middleRadius, MAX_RADIUS, middleRadius, MIN_RADIUS, middleRadius);
firstRadiusAnimation.setRepeatCount(ValueAnimator.INFINITE);
firstRadiusAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float)animation.getAnimatedValue();
mFirstCircle.setRadius(value);
}
});
ValueAnimator secondRadiusAnimation = ValueAnimator.ofFloat(middleRadius, MIN_RADIUS, middleRadius, MAX_RADIUS, middleRadius);
secondRadiusAnimation.setRepeatCount(ValueAnimator.INFINITE);
secondRadiusAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float)animation.getAnimatedValue();
mSecondCircle.setRadius(value);
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(1500);
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
animatorSet.playTogether(firstCenterXAnimation, secondCenterXAnimation, firstRadiusAnimation, secondRadiusAnimation);
animatorSet.start();
}
}
CircleInfo
public class CircleInfo {
private float mCenter;
private float mRadius;
private int mColor;
public void setCenter(float center){
mCenter = center;
}
public float getCenter(){
return mCenter;
}
public void setRadius(float radius){
mRadius = radius;
}
public float getRadius(){
return mRadius;
}
public void setColor(int color){
mColor = color;
}
public int getColor(){
return mColor;
}
}
佈局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cxh.circleprogressbar.MainActivity">
<com.cxh.circleprogressbar.CircleProgressBar
android:layout_width="100dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>