您的位置:首页 > 其它

加载超炫动画

2016-05-17 22:06 218 查看
1、MainActivity

package com.zyhui.zyh_splash;

import android.os.Bundle;
import android.os.Handler;
import android.widget.FrameLayout;
import android.app.Activity;

public class MainActivity extends Activity {

private FrameLayout mMainView;
private SplashView sv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

mMainView = new FrameLayout(this);

ContentView mContentView = new ContentView(this);
mMainView.addView(mContentView);

sv = new SplashView(this);
mMainView.addView(sv);

setContentView(mMainView);

//模拟后台加载数据
startLoadData();
}

Handler handler = new Handler();
private void startLoadData() {
handler.postDelayed(new Runnable(){
@Override
public void run() {
//数据加载

//数据加载完后,加载后面的两个动画
sv.splashAndDisapper();
}

}, 20000);
}

}


2、ContentView

package com.zyhui.zyh_splash;

import android.content.Context;
import android.widget.ImageView;

public class ContentView extends ImageView {

public ContentView(Context context) {
super(context);
setImageResource(R.drawable.spring);
}

}


3、动画视图类

package com.zyhui.zyh_splash;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;

//=======================================
//1、问题:为什么第三个动画后,可以看到第底层图片?
//  答:它没有调用drawbackground方法
//2、问:动画是如何衔接的?
//  答:动画是通过invalidate()方法进行重绘操作的
//3、关于post方法的参考:
//   答:http://www.cnblogs.com/akira90/archive/2013/03/06/2946740.html
//=======================================
public class SplashView extends View {

//大圆半径
private float mRotationRadius = 90;
//小圆半径
private float mCircleRadius = 18;
//小圆圈的颜色列表
private int[] mCircleColors;
//大圆和小圆旋转的时间,可以控制旋转速度
private long mRotationDuration = 3200;//ms
//第二部分动画执行的总时间(各占1/3)
private long mSplashDuration = 3200; //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 mPaintBackground = new Paint();

//屏幕正中心坐标
private float mCenterX;
private float mCenterY;
//屏幕对角线一半
private float mDiagonalDist;

//保存当前动画状态
private SplashState mState = null;
private abstract class SplashState{
public abstract void drawState(Canvas canvas);
}

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);//设置取消锯齿
mPaintBackground.setAntiAlias(true);
//设置边框样式
mPaintBackground.setStyle(Style.STROKE);
mPaintBackground.setColor(mSplashBgColor);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
mCenterX = w/2f;
mCenterY = h/2f;
mDiagonalDist = (float) (Math.sqrt(w*w+h*h)/2);
}
@Override
protected void onDraw(Canvas canvas) {
if(mState == null){
mState = new RotationState();
}
mState.drawState(canvas);
super.onDraw(canvas);
}

//数据加载完之后,加载后面的两个动画
public void splashAndDisapper(){
if(mState != null && mState instanceof RotationState){
RotationState rs = (RotationState) mState;
rs.cancel();//取消第一个动画
post(new Runnable(){
@Override
public void run() {
mState = new MergingState();
}

});
}
}

//旋转类
private class RotationState extends SplashState{
private ValueAnimator mAnimator;
public RotationState(){
//小圆半径,需要大圆半径和它旋转的角度
//估值器--它使用的是弧度0~2PI
mAnimator = ValueAnimator.ofFloat(0, (float)Math.PI*2);
//线性插值器,会平滑地计算;这样在每完成一个周期时,它不会卡顿
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.setDuration(mRotationDuration);//设置旋转时间
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//这个mCurrentRotationAngle这个值的变化,就是造成小圆旋转的原因;若
//这个值不变了,则小圆们就不会旋转
mCurrentRotationAngle = (Float)animation.getAnimatedValue();
//提醒view重绘
invalidate();
}
});

//设置旋转次数--无穷次数;因为它不知道什么时候进入下一个动画,所以把它设置为重复次数为无穷
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
mAnimator.start();
}

@Override
public void drawState(Canvas canvas) {
//实现动画的绘制
//1、清空背景
drawBackground(canvas);
//绘制小圆
drawCircle(canvas);
}

//取消该动画
public void cancel(){
mAnimator.cancel();
}

}

//聚合动画
private class MergingState extends SplashState{
private ValueAnimator mAnimator;
public MergingState(){
//小圆半径,需要大圆半径和它旋转的角度
//估值器
mAnimator = ValueAnimator.ofFloat(0,mRotationRadius);
//插值器-弹射效果的
mAnimator.setInterpolator(new OvershootInterpolator(6f));
mAnimator.setDuration(mSplashDuration/3);//设置动画时间
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurrentRotationRadius = (Float)animation.getAnimatedValue();
//提醒view重绘
invalidate();
}
});

//监听动画执行完毕状态
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//进入下一个动画
mState = new ExpandingState();
}
});
//动画反转过来
mAnimator.reverse();
}

@Override
public void drawState(Canvas canvas) {
//实现动画的绘制
//1、清空背景
drawBackground(canvas);
//绘制小圆
drawCircle(canvas);
}

}

//扩散动画
private class ExpandingState extends SplashState{
private ValueAnimator mAnimator;
public ExpandingState(){
//估值器 --空心圆的半径:0到对角线的一半
mAnimator = ValueAnimator.ofFloat(0,mDiagonalDist);
//插值器-弹射效果的
//mAnimator.setInterpolator(new OvershootInterpolator(6f));
mAnimator.setDuration(mSplashDuration/3);//设置动画时间
mAnimator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//空心圆半径
mHoleRadius = (Float)animation.getAnimatedValue();
//提醒view重绘
invalidate();
}
});

mAnimator.start();
}

@Override
public void drawState(Canvas canvas) {
//1、清空背景
//drawBackground(canvas);
//绘制空心圆效果
if(mHoleRadius > 0f){
//画笔的宽度:对角线的一半 - 空心圆半径
float storkeWidth = mDiagonalDist - mHoleRadius;
mPaintBackground.setStrokeWidth(storkeWidth);

float circleRadius = mHoleRadius + mDiagonalDist / 2f;
canvas.drawCircle(mCenterX, mCenterY, circleRadius, mPaintBackground);
}
}

}

//清空画布
public void drawBackground(Canvas canvas) {
canvas.drawColor(mSplashBgColor);
}

//画多个小圆
public void drawCircle(Canvas canvas) {
//每个小圆的间隔角度
float rotationAngle = (float) (Math.PI*2/mCircleColors.length);

for(int i=0; i<mCircleColors.length; i++){
double angle = mCurrentRotationAngle + i * rotationAngle;
float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle));
float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle));
mPaint.setColor(mCircleColors[i]);
canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
}
}

}


4、颜色值,使用xml进行配置

<?xml version="1.0" encoding="utf-8"?>
<resources>
<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>
</resources>


注:onSizeChanged在什么时候执行呢?可看http://blog.csdn.net/jason0539/article/details/9896743
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: