加载超炫动画
2016-05-17 22:06
218 查看
1、MainActivity
2、ContentView
3、动画视图类
4、颜色值,使用xml进行配置
注:onSizeChanged在什么时候执行呢?可看http://blog.csdn.net/jason0539/article/details/9896743
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
相关文章推荐
- 【转】ConcurrenthashMap
- 第十二章对象(上)
- 第十二章对象(上)
- SQL注入攻击
- C语言游戏和代码
- 对Windows平台C程序内存分布研究及安全性分析
- Linux 终端 使用
- 风险及对策
- Android Drawable Resources系列2:<nine-patch>标签、.9.png图片制作
- dev下没有input 目录和event设备节点
- 浏览器对象模型
- shell-6.shell read 命令
- memcpy的函数内部实现
- Node.js返回JSONP
- ListNode示例
- std::vector的简单实验
- 练习010
- 理解Python中的with…as…语法
- opencv:使用高斯混合模型(GMM)源码对视频进行背景差分法
- objective-c中的self和super关键字