旋转动画

旋转动画

使用的到策略模式

package com.splash.activity;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;

/**
 * 作者: songli
 * QQ : 2734030745
 * 时间: 2017/6/16 2:28
 * 邮箱: 15850774503@163.com.
 */

public class SplashView extends View {
    private ValueAnimator mAnimator;
    //大圆的半径
    private float mRotationRadius = 90;
    //每个小圆的半径
    private float mCircleRadius = 18;

    //小圆的颜色列表, 在initialize方法里面初始化
    private int[] mCircleColors;

    //大圆和小圆旋转的时间
    private long mRotationDuration = 1200; //ms
    //第二部分动画的执行总时间
    private long mSplashDuration = 1200; //ms
    //整体的背景颜色
    private int mSplashBgColor = Color.WHITE;

    //空心圆初始半径
    private float mHoleRadius = 0F;
    //当前大圆旋转角度
    private float mCurrentRotationAngle = 0F;
    //当前大圆的半径
    private float mCurrentRotationRadius = mRotationRadius;

    //绘制圆的画笔
    private Paint mPaint = new Paint();
    //绘制背景的画笔
    private Paint mPaitnBackground = new Paint();

    //屏幕正中心点坐标
    private float mCenterX;
    private float mCenterY;

    //屏幕对角线一半
    private float mDiagonalDist;


    public SplashView(Context context) {
        super(context);
        init(context);
    }

    public SplashView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }


    private void init(Context context) {
        mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors);
        //画笔初始化
        //消除锯齿
        mPaint.setAntiAlias(true);
        mPaitnBackground.setAntiAlias(true);
        //设置样式----边框样式----描边
        mPaitnBackground.setStyle(Paint.Style.STROKE);
        mPaitnBackground.setColor(mSplashBgColor);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mCenterX = w / 2f;
        mCenterY = h / 2f;
        mDiagonalDist = (float) (Math.sqrt((w * w + h * h)) / 2f);
    }

    public void splashDisappear() {
        //开启后面两个动画
        //换模板---换状态
        if (mState != null && mState instanceof RoateState)
        {

            //结束旋转动画
            RoateState roateState = (RoateState) mState;
            roateState.cancel();
            post(new Runnable() {
                @Override
                public void run() {
                    mState = new MergingState();
                }
            });
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mState == null)
        {
            //开启第一个旋转动画
            mState = new RoateState();
        }
        //调用 绘制方法
        mState.drawState(canvas);
    }

    private SplashState mState = null;

    策略模式:State---三种动画状态
    private abstract class SplashState {
        public abstract void drawState(Canvas canvas);
    }



    /**
     * 1,旋转动画
     * 控制各个小圆的坐标 --- 控制小圆的角度变化--属性动画ValueAnimator
     */

    private class RoateState extends SplashState {

        public RoateState() {

            //1,动画的初始工作, 2,开启动画
            //花1200ms ,计算某个时刻当前的角度是多少? 0 - 2π
            mAnimator = ValueAnimator.ofFloat(0f, (float) Math.PI * 2);
            mAnimator.setInterpolator(new LinearInterpolator());
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    //计算某个时刻当前的大圆旋转了的角度是多少?
                    mCurrentRotationAngle = (float) animation.getAnimatedValue();

                    invalidate();
                }
            });

            mAnimator.setDuration(mRotationDuration);
            mAnimator.setRepeatCount(ValueAnimator.INFINITE);
            mAnimator.start();

        }

        public void cancel() {
            mAnimator.cancel();
        }

        @Override
        public void drawState(Canvas canvas) {

            //1,背景----涂层白色
            drawBackground(canvas);
            //2,绘制小圆
            drawCircles(canvas);
        }
    }


    /**
     * 2,
     */
    private class MergingState extends SplashState {
        public MergingState() {
            //花1200ms, 计算某个时刻当前的大圆半径是多少?  r ~ 0 中的某个值
            mAnimator = ValueAnimator.ofFloat(0, mRotationRadius);
            mAnimator.setDuration(mRotationDuration);
            mAnimator.setInterpolator(new OvershootInterpolator(10f));
            mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    //某个时刻当前大圆的半径是多少?
                    mCurrentRotationRadius = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });

            mAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {

                    mState = new ExpandState();
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            mAnimator.reverse();
        }

        @Override
        public void drawState(Canvas canvas) {
//1,背景----涂层白色
            drawBackground(canvas);
            //2,绘制小圆
            drawCircles(canvas);
        }
    }

    /**
     * 3,水波纹扩散动画
     * 画一个空心圆----画一个圆,让它的画笔的粗细变成很大---不断地减小画笔的粗细。
     * 空心圆变化的范围:0~ 对角线/2
     */
    private class  ExpandState extends SplashState
    {

        public ExpandState() {
            //花1200ms,计算某个时刻当前的空心圆的半径是多少? r~0中的某个值
            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);
        }
    }
    private void drawCircles(Canvas canvas) {
        //每个小圆的之间的间隔角度 = 2π/小圆的个数
        float rotationAngle = (float) (2 * Math.PI / mCircleColors.length);

        for (int i = 0; i < mCircleColors.length; i++) {
            /**
             * x = r * cos(a) + centerX
             * y = r *  sin(a) + centerY
             * 每个小圆i* 间隔 角度 + 旋转 的角度 = 当前小圆的真的角度
             */
            double angle = i * rotationAngle + mCurrentRotationAngle;
            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 void drawBackground(Canvas canvas) {
        if (mHoleRadius > 0f) {
            //得到画笔的宽度  = 对角线 / 2 - 空心圆的半径
            float strokeWidth = mDiagonalDist - mHoleRadius;
            mPaitnBackground.setStrokeWidth(strokeWidth);
            //画圆的半径== 空心圆的半径 + 画笔的宽度  / 2
            float radius = mHoleRadius + strokeWidth / 2;
            canvas.drawCircle(mCenterX, mCenterY, radius, mPaint);
        } else {
            canvas.drawColor(mSplashBgColor);
        }

    }

}
package com.splash.activity;

import android.content.Context;
import android.support.v7.widget.AppCompatImageView;


/**
 * 作者: songli
 * QQ : 2734030745
 * 时间: 2017/6/16 2:25
 * 邮箱: 15850774503@163.com.
 */

public class ContentView extends AppCompatImageView {
    public ContentView(Context context) {
        super(context);

        setImageResource(R.mipmap.content);
    }
}
package com.splash.activity;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.FrameLayout;

public class MainActivity extends AppCompatActivity {


    private FrameLayout mMainView;
    private SplashView splashView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);

        mMainView = new FrameLayout(this);
        ContentView contentView = new ContentView(this);
        mMainView.addView(contentView);
        splashView = new SplashView(this);
        mMainView.addView(splashView);
        setContentView(mMainView);
        //后台加载数据
        startLoadData();
    }

    Handler handler = new Handler();
    private void startLoadData() {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //数据加载一半 进入主界面 --> 开启
                splashView.splashDisappear();
            }
        }, 6000); //延迟时间
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值