旋转动画
使用的到策略模式
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); //延迟时间
}
}