自定义启动页动画

今天学习了一下自定义 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);
        }
    }

}

如果有什么不对地方,请大家多多指正!欢迎评论

发布了20 篇原创文章 · 获赞 5 · 访问量 9491

猜你喜欢

转载自blog.csdn.net/Small_Wave_Wave/article/details/96319637