public class SplashView extends View {
// 旋转圆的画笔
private Paint mPaint;
// 扩散圆的画笔
private Paint mHolePaint;
// 属性动画
private ValueAnimator mValueAnimator;
// 背景色
private int mBackgroundColor = Color.WHITE;
// 每个小球颜色
private int[] mCircleColors;
// 旋转圆的中心坐标
private float mCenterX;
private float mCenterY;
// 斜对角线的一半,扩散圆的最大半径
private float mDistance;
// 6个小球的半径
private float mCircleRadius = 18;
// 旋转大圆的半径
private float mRotateRadius = 90;
// 当前大圆旋转角度
private float mCurrentRotateAngel = 0F;
// 当前大圆的半径
private float mCurrentRotateRadius = mRotateRadius;
// 扩散圆的半径
private float mCurrentHoleRadius = 0F;
// 旋转动画时长
private int mRotateDuration = 1200;
private SplashState mState;
public SplashView(Context context) {
this(context,null);
}
public SplashView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public SplashView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHolePaint.setStyle(Paint.Style.STROKE);
mHolePaint.setColor(mBackgroundColor);
mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 计算中心点坐标
mCenterX = w * 1f /2;
mCenterY = h * 1f /2;
mDistance = (float) (Math.hypot(w,h)/2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 先初始化旋转动画
if (mState == null){
mState = new RotateState();
}
mState.drawState(canvas);
}
private abstract class SplashState{
abstract void drawState(Canvas canvas);
}
/**
* 1.旋转
*/
private class RotateState extends SplashState{
RotateState(){
mValueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI*2)) ;
// 旋转2次
mValueAnimator.setRepeatCount(2);
mValueAnimator.setDuration(mRotateDuration);
mValueAnimator.setInterpolator(new LinearInterpolator());
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 改变切换角度
mCurrentRotateAngel = (float) valueAnimator.getAnimatedValue();
// 重新触发onDraw
invalidate();
}
});
mValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// 切换扩散动画
mState = new MerginState();
}
});
// 执行动画
mValueAnimator.start();
}
@Override
void drawState(Canvas canvas) {
// 绘制背景
drawBackground(canvas);
// 绘制6个小球
drawCircles(canvas);
}
}
/**
* 2.扩散
*/
private class MerginState extends SplashState {
MerginState() {
mValueAnimator = ValueAnimator.ofFloat(mCircleRadius, mRotateRadius);
mValueAnimator.setDuration(mRotateDuration);
mValueAnimator.setInterpolator(new OvershootInterpolator(10f));
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 改变扩散大圆的半径
mCurrentRotateRadius = (float) valueAnimator.getAnimatedValue();
// 重新触发onDraw
invalidate();
}
});
mValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mState = new ExpandState();
}
});
// 执行动画
mValueAnimator.reverse();
}
@Override
void drawState(Canvas canvas) {
// 绘制背景
drawBackground(canvas);
// 绘制6个小球
drawCircles(canvas);
}
}
/**
* 3. 水波纹
*/
private class ExpandState extends SplashState {
ExpandState() {
mValueAnimator = ValueAnimator.ofFloat(mCircleRadius, mDistance);
mValueAnimator.setDuration(mRotateDuration);
mValueAnimator.setInterpolator(new LinearInterpolator());
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 扩散圆的半径
mCurrentHoleRadius = (float) valueAnimator.getAnimatedValue();
// 重新触发onDraw
invalidate();
}
});
// 执行动画
mValueAnimator.start();
}
@Override
void drawState(Canvas canvas) {
// 绘制背景
drawBackground(canvas);
}
}
/**
* 绘制6个小球
* @param canvas
*/
private void drawCircles(Canvas canvas) {
// 6个小球评分角度
float rotateAngle = (float) (Math.PI * 2 / mCircleColors.length);
for (int i = 0; i < mCircleColors.length; i++) {
float angel = i*rotateAngle + mCurrentRotateAngel;
// 每个小球的中心点坐标
float cx = (float) (Math.cos(angel) * mRotateRadius+mCenterX);
float cy = (float) (Math.sin(angel) * mRotateRadius+mCenterY);
mPaint.setColor(mCircleColors[i]);
// 绘制小球
canvas.drawCircle(cx,cy,mCircleRadius,mPaint);
}
}
private void drawBackground(Canvas canvas) {
if (mCurrentHoleRadius>0){
// 绘制空心圆
float strokeWidth = mDistance - mCurrentHoleRadius;
// 半径
float radius = strokeWidth / 2 + mCurrentHoleRadius;
mHolePaint.setStrokeWidth(strokeWidth);
canvas.drawCircle(mCenterX,mCenterY,radius,mHolePaint);
}else{
canvas.drawColor(mBackgroundColor);
}
}
}
颜色数组,可自定义
<array name="splash_circle_colors">
<item>@color/color_F71816</item>
<item>@android:color/holo_orange_dark</item>
<item>@android:color/holo_blue_dark</item>
<item>@android:color/holo_purple</item>
<item>@android:color/darker_gray</item>
<item>@android:color/holo_green_dark</item>
</array>