今天學習了一下自定義 View 實現啓動頁面動畫到效果,上一下效果圖
簡單說一下過程
1、首先畫白色背景和六個不同顏色到小球
白色背景直接 canvas.drawColor(backgroundColor);
小球這裏說一下,六個小球圍成一個圓,那麼我們就先要計算出來兩個小球之間的角度是多少
獲取圓的周長除以小球個數
//先獲取圓球之間的角度 圓周長 2PI
float rotateAngle = (float) ((Math.PI * 2) / circleColor.length);
然後 for 循環繪製小球
canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
首先需要確定圓心座標,半徑是咱們規定好的
計算cx,cy需要一點點三角函數的知識
如圖
貼上計算代碼
//先獲取圓球之間的角度 圓周長 2PI
float rotateAngle = (float) ((Math.PI * 2) / circleColor.length);
for (int i = 0; i < circleColor.length; i++) {
//x=r*cons(a)+cenX
//y=r*sin(a)+cenY
float angle = i * rotateAngle + mCurrentRotateAngle;
float cx = (float) (Math.cos(angle) * mCurrentRotateRadius + mCenterX);
float cy = (float) (Math.sin(angle) * mCurrentRotateRadius + mCenterY);
mPaint.setColor(circleColor[i]);
canvas.drawCircle(cx, cy, smallCircleRadius, mPaint);
}
然後我們在寫一個 ValueAnimator 用來控制小球旋轉的
valueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2));//從0開始 圓的一週結束
valueAnimator.setRepeatCount(2);//次數
valueAnimator.setDuration(mRotateDuration);//時長
valueAnimator.setInterpolator(new LinearInterpolator());//勻速
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotateAngle = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
splashState = new MerginState();
}
});
valueAnimator.start();
這個時候就可以看到六個小球在屏幕中間 開始旋轉了
2、旋轉完後 小球開始擴散後中心聚合
valueAnimator = ValueAnimator.ofFloat(smallCircleRadius, circleRadius);
valueAnimator.setDuration(mRotateDuration);
valueAnimator.setInterpolator(new OvershootInterpolator(10f));
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotateRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
splashState = new ExpandState();
}
});
valueAnimator.reverse();
3、最後就是我們的波紋效果了
valueAnimator = ValueAnimator.ofFloat(smallCircleRadius, mDistance);
valueAnimator.setDuration(mRotateDuration);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentHoleRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
到此炫酷的啓動動畫就已經完成了,是不是很簡單那,上一個完整的自己的 View 類
/**
* @author wavewave
* @CreateDate: 2019-07-16 22:46
* @Description:
* @Version: 1.0
*/
public class SplashView extends View {
//背景顏色
private int backgroundColor = Color.WHITE;
private int[] circleColor = new int[]{
Color.RED, Color.GREEN, Color.BLUE,
Color.GRAY, Color.DKGRAY, Color.BLACK};
private int smallCircleRadius = 10;
private int circleRadius = 99;
private float mCenterX, mCenterY;
private float mDistance;
private Paint mPaint;
private SplashState splashState;
private int mRotateDuration = 800;
private float mCurrentRotateRadius = circleRadius;
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();
}
private void init() {
mPaint = new Paint();
}
@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 (splashState == null) {
splashState = new RotateState();
}
splashState.drawState(canvas);
}
//動畫效果 6個不同顏色的球圍城一個圓 ,開始旋轉。然後擴散再聚合到中心,最後水波紋效果
/**
* 抽象類
* 表示繪製狀態
*/
public abstract class SplashState {
abstract void drawState(Canvas canvas);
}
/**
* 繪製背景顏色
*
* @param canvas
*/
private void drawBackground(Canvas canvas) {
if (mCurrentHoleRadius > 0) {//第三種動畫 繪製空心圓
float strokeWidth = mDistance - mCurrentHoleRadius;
float radius = strokeWidth / 2 + mCurrentHoleRadius;
mPaint.setStrokeWidth(radius);
canvas.drawCircle(mCenterX, mCenterY, radius, mPaint);
} else {
canvas.drawColor(backgroundColor);
}
}
/**
* 繪製小球
*
* @param canvas
*/
private void drawCircle(Canvas canvas) {
//先獲取圓球之間的角度 圓周長 2PI
float rotateAngle = (float) ((Math.PI * 2) / circleColor.length);
for (int i = 0; i < circleColor.length; i++) {
//x=r*cons(a)+cenX
//y=r*sin(a)+cenY
float angle = i * rotateAngle + mCurrentRotateAngle;
float cx = (float) (Math.cos(angle) * mCurrentRotateRadius + mCenterX);
float cy = (float) (Math.sin(angle) * mCurrentRotateRadius + mCenterY);
mPaint.setColor(circleColor[i]);
canvas.drawCircle(cx, cy, smallCircleRadius, mPaint);
}
}
private float mCurrentRotateAngle;
private ValueAnimator valueAnimator;
//1 旋轉
private class RotateState extends SplashState {
public RotateState() {
valueAnimator = ValueAnimator.ofFloat(0, (float) (Math.PI * 2));//從0開始 圓的一週結束
valueAnimator.setRepeatCount(2);//次數
valueAnimator.setDuration(mRotateDuration);//時長
valueAnimator.setInterpolator(new LinearInterpolator());//勻速
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotateAngle = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
splashState = new MerginState();
}
});
valueAnimator.start();
}
@Override
void drawState(Canvas canvas) {
//繪製白色背景
drawBackground(canvas);
//繪製圓
drawCircle(canvas);
}
}
//2 擴展聚合
private class MerginState extends SplashState {
public MerginState() {
valueAnimator = ValueAnimator.ofFloat(smallCircleRadius, circleRadius);
valueAnimator.setDuration(mRotateDuration);
valueAnimator.setInterpolator(new OvershootInterpolator(10f));
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotateRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
splashState = new ExpandState();
}
});
valueAnimator.reverse();
}
@Override
void drawState(Canvas canvas) {
//繪製白色背景
drawBackground(canvas);
//繪製圓
drawCircle(canvas);
}
}
private float mCurrentHoleRadius;
//3 波紋效果
private class ExpandState extends SplashState {
public ExpandState() {
valueAnimator = ValueAnimator.ofFloat(smallCircleRadius, mDistance);
valueAnimator.setDuration(mRotateDuration);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentHoleRadius = (float) animation.getAnimatedValue();
invalidate();
}
});
valueAnimator.start();
}
@Override
void drawState(Canvas canvas) {
drawBackground(canvas);
}
}
}
如果有什麼不對地方,請大家多多指正!歡迎評論