參考:
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