目标效果:
代码实现:
public class PlayingView extends View {
private ValueAnimator mValueAnimatorA;
private ValueAnimator mValueAnimatorB;
private ValueAnimator mValueAnimatorC;
private float mWidth;
private float mHeight;
private float topA;
private float topB;
private float topC;
private float rectWidth;
private float perHeight;
private float radius;
private Paint mPaint;
private RectF mRectFA;
private RectF mRectFB;
private RectF mRectFC;
public PlayingView(Context context) {
super(context);
}
public PlayingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(getResources().getColor(R.color.main_color));
}
public PlayingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public PlayingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
rectWidth = mWidth / 6;
perHeight = mHeight / 4;
radius = rectWidth / 2;
topA = mHeight - perHeight;
topB = topA;
topC = topA;
float margin = rectWidth / 2;
mRectFA = new RectF(margin, topA, rectWidth + margin, mHeight);
mRectFB = new RectF(2 * rectWidth + margin, topB, 3 * rectWidth + margin, mHeight);
mRectFC = new RectF(4 * rectWidth + margin, topC, 5 * rectWidth + margin, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mValueAnimatorA == null) {
mValueAnimatorA = getValueAnimator();
mValueAnimatorA.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
topA = (float) animation.getAnimatedValue();
}
});
mValueAnimatorA.setStartDelay(200);
mValueAnimatorA.start();
mValueAnimatorB = getValueAnimator();
mValueAnimatorB.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
topB = (float) animation.getAnimatedValue();
PlayingView.this.postInvalidate();
}
});
mValueAnimatorB.start();
mValueAnimatorC = getValueAnimator();
mValueAnimatorC.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
topC = (float) animation.getAnimatedValue();
}
});
mValueAnimatorC.setStartDelay(400);
mValueAnimatorC.start();
}
mRectFA.top = topA;
mRectFB.top = topB;
mRectFC.top = topC;
canvas.drawRoundRect(mRectFA, radius, radius, mPaint);
canvas.drawRoundRect(mRectFB, radius, radius, mPaint);
canvas.drawRoundRect(mRectFC, radius, radius, mPaint);
}
private ValueAnimator getValueAnimator() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(mHeight - perHeight, perHeight);
valueAnimator.setDuration(600);
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
return valueAnimator;
}
}