之前在知乎看到过一个网易云音乐听歌识曲界面的自定义View,实现的是一个带有水波纹扩散效果的控件,实现原理是ObjectAnimator,效果如下。
下面贴一下代码:
public class SunmiWaveView extends View {
//圆圈个数
int mCircleCount = 6;
//圆圈之间的间隔
int mInterval = 500;
//每个圆圈的动画周期
int mDuration = 3000;
//透明度初始值
int mStartAlpha = 105;
int mEndAlpha = 0;
//半径初始值
int mStartRadius = 0;
int mEndRadius = 150;
private float radio = 0.75f;
//动画开始时间
long mAnimaStartTime;
boolean isRunning;
Interpolator mInterpolator = new LinearOutSlowInInterpolator();
Circle[] mCircles;
private Paint mPaint;
public SunmiWaveView(Context context) {
super(context);
initCircles();
initPaint();
}
public SunmiWaveView(Context context, AttributeSet attrs) {
super(context, attrs);
initCircles();
initPaint();
}
private void initCircles() {
mCircles = new Circle[mCircleCount];
for (int i = 0; i < mCircles.length; i++) {
mCircles[i] = new Circle();
}
}
private void initPaint() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mEndRadius = (int) (Math.min(w, h) * radio / 2f);
}
@Override
protected void onDraw(Canvas canvas) {
if (mAnimaStartTime == 0 || !isRunning)
return;
long pastTime = System.currentTimeMillis() - mAnimaStartTime;
for (int i = 0; i < mCircleCount; i++) {
int delay = i * mInterval;
long pastTimeTrue = pastTime - delay;
long timeInDuration = pastTimeTrue < 0 ? 0 : pastTimeTrue % mDuration;
float percent = timeInDuration * 1f / mDuration;
float percentWithInterpolate = mInterpolator.getInterpolation(percent);
mCircles[i].radius = mStartRadius + (mEndRadius - mStartRadius) * percentWithInterpolate;
mCircles[i].alpha = mStartAlpha + (int) ((mEndAlpha - mStartAlpha) * percentWithInterpolate);
mPaint.setAlpha(mCircles[i].alpha);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mCircles[i].radius, mPaint);
// System.out.println("circle" + i + ": " + mCircles[i]);
}
postInvalidateDelayed(10);
}
public void start() {
isRunning = true;
mAnimaStartTime = System.currentTimeMillis();
invalidate();
}
public void stop() {
isRunning = false;
for (Circle circle : mCircles) {
circle.reset();
}
}
public void setColor(int color) {
mPaint.setColor(color);
}
public static class Circle {
public int alpha;
public float radius;
public void reset() {
alpha = 0;
radius = 0;
}
@Override
public String toString() {
return "alpha: " + alpha + " radius: " + radius;
}
}