参考:
https://www.jianshu.com/p/6dd6c89220d9
https://blog.csdn.net/u010008118/article/details/103070847
https://blog.csdn.net/u014133119/article/details/80998025
效果展示
绘制六个圆
1 初始化
在colors.xml中添加6个颜色
<color name="splash_bg">#F8F6EC</color>
<color name="orange">#FF9600</color>
<color name="aqua">#02D1AC</color>
<color name="yellow">#FFD200</color>
<color name="blue">#00C6FF</color>
<color name="green">#00E099</color>
<color name="pink">#FF3892</color>
<array name="splash_circle_colors">
<item>@color/blue</item>
<item>@color/green</item>
<item>@color/pink</item>
<item>@color/orange</item>
<item>@color/aqua</item>
<item>@color/yellow</item>
</array>
初始化颜色和画笔
// 小圆圈的颜色列表,在initialize方法里面初始化
private int[] mCircleColors;
// 绘制圆的画笔
private Paint mPaint = new Paint();
public SplashView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors);
//消除锯齿
mPaint.setAntiAlias(true);
}
确定屏幕中心点坐标
// 屏幕正中心点坐标
private float mCenterX;
private float mCenterY;
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w / 2f;
mCenterY = h / 2f;
}
2 绘制六个小圆
mCircleColors这里一共是6中颜色,分别对应6个小圆颜色
小圆间隔角度= 2π/小圆的个数
当前小圆的角度 = i * 间隔角度
当前小圆的 x坐标 = 小圆半径cos(a) + 小圆心X坐标
当前小圆的 y坐标 = 小圆半径sin(a) + 小圆心Y坐标
// 大圆(里面包含很多小圆的)的半径
private float mRotationRadius = 90;
// 每一个小圆的半径
private float mCircleRadius = 18;
//当前大圆的半径
private float mCurrentRotationRadius = mRotationRadius;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircles(canvas);
}
private void drawCircles(Canvas canvas) {
//每个小圆之间的间隔角度= 2π / 小圆的个数
float rotetionAngle = (float) (2 * Math.PI / mCircleColors.length);
for (int i = 0; i < mCircleColors.length; i++) {
/**
* x= r* cos(a) + centerX
* y = r* sin(a) + centerY
*/
double angle = i * rotetionAngle ;
float cx = (float) (mCurrentRotationRadius * Math.cos(angle) + mCenterX);
float cy = (float) (mCurrentRotationRadius * Math.sin(angle) + mCenterY);
mPaint.setColor(mCircleColors[i]);
canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
}
}
动画
- 刚进来时执行旋转动画
- 数据加载完毕之后调用聚合逃逸动画
- 聚合逃逸动画完成之后,进行扩散
使用策略模式控制状态转变,一种状态控制一个动画
/**
* 策略模式(状态模式),每一种状态是一个绘制
*/
private abstract class SplashState {
public abstract void drawState(Canvas canvas);
public void cancle() {
}
}
/**
* 旋转动画
*/
private class RotateState extends SplashState {
@Override
public void drawState(Canvas canvas) {
}
}
/**
* 聚合动画
*/
private class MerginState extends SplashState {
@Override
public void drawState(Canvas canvas) {
}
}
/**
* 扩散动画
*/
private class ExpandState extends SplashState {
@Override
public void drawState(Canvas canvas) {
}
}
//1、旋转动画
private class RotateState extends SplashState {
public RotateState() {
//1、动画的初始化工作,2、开启动画
mAnimator = ValueAnimator.ofFloat(0f, (float) Math.PI * 2);
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCurrentRotationAngle = (float) valueAnimator.getAnimatedValue();
postInvalidate();
}
});
mAnimator.setDuration(mRotationDuration);
//无限循环
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
//背景
drawBackground(canvas);
//绘制小圆
drawCircles(canvas);
}
}
//执行聚合动画
public void splashDisappear() {
if (mState != null && mState instanceof RotateState) {
RotateState rotateState = (RotateState) mState;
rotateState.cencel();
post(new Runnable() {
@Override
public void run() {
mState = new MergingState();
}
});
}
}
//2、聚合动画
private class MergingState extends SplashState {
public MergingState() {
mAnimator = ValueAnimator.ofFloat(0f, mRotationRadius);
mAnimator.setDuration(mRotationDuration);
mAnimator.setInterpolator(new OvershootInterpolator(10f));// 向前甩一定值后再回到原来位置
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mCurrentRotationRadius = (float) valueAnimator.getAnimatedValue();
invalidate();
}
});
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mState = new ExpandState();
}
});
//反转
mAnimator.reverse();
}
@Override
public void drawState(Canvas canvas) {
//背景
drawBackground(canvas);
//绘制小圆
drawCircles(canvas);
}
}
//3、水波纹扩散动画
private class ExpandState extends SplashState {
public ExpandState() {
mAnimator = ValueAnimator.ofFloat(mCircleRadius, mDiagonalDist);
mAnimator.setDuration(mRotationDuration);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mHoleRadius = (float) valueAnimator.getAnimatedValue();
invalidate();
}
});
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
drawBackground(canvas);
}
}
public class MainActivity extends AppCompatActivity {
private SplashView splashView;
private FrameLayout mMainView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMainView = new FrameLayout(this);
ContentView contentView = new ContentView(this);
mMainView.addView(contentView);
splashView = new SplashView(this);
mMainView.addView(splashView);
setContentView(mMainView);
startLoaddData();
}
private void startLoaddData() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//表示数据加载完毕,进入第二个状态
splashView.splashDisappear();
}
}, 3000);//延时时间
}
}
Github:https://github.com/345166018/AndroidUI/tree/master/HxSplashView