加载超炫动画

1、MainActivity

 1 package com.zyhui.zyh_splash;
 2 
 3 import android.os.Bundle;
 4 import android.os.Handler;
 5 import android.widget.FrameLayout;
 6 import android.app.Activity;
 7 
 8 public class MainActivity extends Activity {
 9 
10     private FrameLayout mMainView;
11     private SplashView sv;
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         
17         mMainView = new FrameLayout(this);
18         
19         ContentView mContentView = new ContentView(this);
20         mMainView.addView(mContentView);
21         
22         sv = new SplashView(this);
23         mMainView.addView(sv);
24         
25         setContentView(mMainView);
26         
27         //模拟后台加载数据
28         startLoadData();
29     }
30 
31     Handler handler = new Handler();
32     private void startLoadData() {
33         handler.postDelayed(new Runnable(){
34             @Override
35             public void run() {
36                 //数据加载
37                 
38                 //数据加载完后,加载后面的两个动画
39                 sv.splashAndDisapper();
40             }
41             
42         }, 20000);
43     }
44 
45 
46 }

2、ContentView

 1 package com.zyhui.zyh_splash;
 2 
 3 import android.content.Context;
 4 import android.widget.ImageView;
 5 
 6 public class ContentView extends ImageView {
 7 
 8     public ContentView(Context context) {
 9         super(context);
10         setImageResource(R.drawable.spring);
11     }
12 
13 }

3、动画视图类

  1 package com.zyhui.zyh_splash;
  2 
  3 import android.animation.Animator;
  4 import android.animation.AnimatorListenerAdapter;
  5 import android.animation.ValueAnimator;
  6 import android.animation.ValueAnimator.AnimatorUpdateListener;
  7 import android.content.Context;
  8 import android.graphics.Canvas;
  9 import android.graphics.Color;
 10 import android.graphics.Paint;
 11 import android.graphics.Paint.Style;
 12 import android.view.View;
 13 import android.view.animation.LinearInterpolator;
 14 import android.view.animation.OvershootInterpolator;
 15 
 16 //=======================================
 17 //1、问题:为什么第三个动画后,可以看到第底层图片?
 18 //  答:它没有调用drawbackground方法
 19 //2、问:动画是如何衔接的?
 20 //  答:动画是通过invalidate()方法进行重绘操作的
 21 //3、关于post方法的参考:
 22 //   答:http://www.cnblogs.com/akira90/archive/2013/03/06/2946740.html
 23 //=======================================
 24 public class SplashView extends View {
 25 
 26     //大圆半径
 27     private float mRotationRadius = 90;
 28     //小圆半径
 29     private float mCircleRadius = 18;
 30     //小圆圈的颜色列表
 31     private int[] mCircleColors;
 32     //大圆和小圆旋转的时间,可以控制旋转速度
 33     private long mRotationDuration = 3200;//ms
 34     //第二部分动画执行的总时间(各占1/3)
 35     private long mSplashDuration = 3200; //ms
 36     //整体的背景颜色
 37     private int mSplashBgColor = Color.WHITE;
 38     
 39     //空心圆初始半径
 40     private float mHoleRadius = 0F;
 41     //当前大圆旋转的角度
 42     private float mCurrentRotationAngle = 0F;
 43     //当前大圆半径
 44     private float mCurrentRotationRadius = mRotationRadius;
 45     
 46     //绘制圆的画笔
 47     private Paint mPaint = new Paint();
 48     //绘制背景画笔
 49     private Paint mPaintBackground = new Paint();
 50     
 51     //屏幕正中心坐标
 52     private float mCenterX;
 53     private float mCenterY;
 54     //屏幕对角线一半
 55     private float mDiagonalDist;
 56     
 57     //保存当前动画状态
 58     private SplashState mState = null;
 59     private abstract class SplashState{
 60         public abstract void drawState(Canvas canvas);
 61     }
 62     
 63     public SplashView(Context context) {
 64         super(context);
 65         init(context);
 66     }
 67     
 68     private void init(Context context) {
 69         mCircleColors = context.getResources().getIntArray(R.array.splash_circle_colors);
 70         
 71         //设置画笔
 72         mPaint.setAntiAlias(true);//设置取消锯齿
 73         mPaintBackground.setAntiAlias(true);
 74         //设置边框样式
 75         mPaintBackground.setStyle(Style.STROKE);
 76         mPaintBackground.setColor(mSplashBgColor);
 77     }
 78     
 79     @Override
 80     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
 81         // TODO Auto-generated method stub
 82         super.onSizeChanged(w, h, oldw, oldh);
 83         mCenterX = w/2f;
 84         mCenterY = h/2f;
 85         mDiagonalDist = (float) (Math.sqrt(w*w+h*h)/2);
 86     }
 87     @Override
 88     protected void onDraw(Canvas canvas) {
 89         if(mState == null){
 90             mState = new RotationState();
 91         }
 92         mState.drawState(canvas);
 93         super.onDraw(canvas);
 94     }
 95 
 96     //数据加载完之后,加载后面的两个动画
 97     public void splashAndDisapper(){
 98         if(mState != null && mState instanceof RotationState){
 99             RotationState rs = (RotationState) mState;
100             rs.cancel();//取消第一个动画
101             post(new Runnable(){
102                 @Override
103                 public void run() {
104                     mState = new MergingState();
105                 }
106                 
107             });
108         }
109     }
110     
111     //旋转类
112     private class RotationState extends SplashState{
113         private ValueAnimator mAnimator;
114         public RotationState(){
115             //小圆半径,需要大圆半径和它旋转的角度
116             //估值器--它使用的是弧度0~2PI
117             mAnimator = ValueAnimator.ofFloat(0, (float)Math.PI*2);
118             //线性插值器,会平滑地计算;这样在每完成一个周期时,它不会卡顿
119             mAnimator.setInterpolator(new LinearInterpolator());
120             mAnimator.setDuration(mRotationDuration);//设置旋转时间
121             mAnimator.addUpdateListener(new AnimatorUpdateListener() {
122                 @Override
123                 public void onAnimationUpdate(ValueAnimator animation) {
124                     //这个mCurrentRotationAngle这个值的变化,就是造成小圆旋转的原因;若
125                     //这个值不变了,则小圆们就不会旋转
126                     mCurrentRotationAngle = (Float)animation.getAnimatedValue();
127                     //提醒view重绘
128                     invalidate();
129                 }
130             });
131             
132             //设置旋转次数--无穷次数;因为它不知道什么时候进入下一个动画,所以把它设置为重复次数为无穷
133             mAnimator.setRepeatCount(ValueAnimator.INFINITE);
134             mAnimator.start();
135         }
136         
137         @Override
138         public void drawState(Canvas canvas) {
139             //实现动画的绘制
140             //1、清空背景
141             drawBackground(canvas);
142             //绘制小圆
143             drawCircle(canvas);
144         }
145         
146         //取消该动画
147         public void cancel(){
148             mAnimator.cancel();
149         }
150         
151     }
152     
153     //聚合动画
154     private class MergingState extends SplashState{
155         private ValueAnimator mAnimator;
156         public MergingState(){
157             //小圆半径,需要大圆半径和它旋转的角度
158             //估值器
159             mAnimator = ValueAnimator.ofFloat(0,mRotationRadius);
160             //插值器-弹射效果的
161             mAnimator.setInterpolator(new OvershootInterpolator(6f));
162             mAnimator.setDuration(mSplashDuration/3);//设置动画时间
163             mAnimator.addUpdateListener(new AnimatorUpdateListener() {
164                 @Override
165                 public void onAnimationUpdate(ValueAnimator animation) {
166                     mCurrentRotationRadius = (Float)animation.getAnimatedValue();
167                     //提醒view重绘
168                     invalidate();
169                 }
170             });
171             
172             //监听动画执行完毕状态
173             mAnimator.addListener(new AnimatorListenerAdapter() {
174                 @Override
175                 public void onAnimationEnd(Animator animation) {
176                     super.onAnimationEnd(animation);
177                     //进入下一个动画
178                     mState = new ExpandingState();
179                 }
180             });
181             //动画反转过来
182             mAnimator.reverse();
183         }
184         
185         @Override
186         public void drawState(Canvas canvas) {
187             //实现动画的绘制
188             //1、清空背景
189             drawBackground(canvas);
190             //绘制小圆
191             drawCircle(canvas);
192         }
193         
194     }
195     
196     //扩散动画
197     private class ExpandingState extends SplashState{
198         private ValueAnimator mAnimator;
199         public ExpandingState(){
200             //估值器 --空心圆的半径:0到对角线的一半
201             mAnimator = ValueAnimator.ofFloat(0,mDiagonalDist);
202             //插值器-弹射效果的
203             //mAnimator.setInterpolator(new OvershootInterpolator(6f));
204             mAnimator.setDuration(mSplashDuration/3);//设置动画时间
205             mAnimator.addUpdateListener(new AnimatorUpdateListener() {
206                 @Override
207                 public void onAnimationUpdate(ValueAnimator animation) {
208                     //空心圆半径
209                     mHoleRadius = (Float)animation.getAnimatedValue();
210                     //提醒view重绘
211                     invalidate();
212                 }
213             });
214             
215             
216             mAnimator.start();
217         }
218         
219         @Override
220         public void drawState(Canvas canvas) {
221             //1、清空背景
222             //drawBackground(canvas);
223             //绘制空心圆效果
224             if(mHoleRadius > 0f){
225                 //画笔的宽度:对角线的一半 - 空心圆半径
226                 float storkeWidth = mDiagonalDist - mHoleRadius;
227                 mPaintBackground.setStrokeWidth(storkeWidth);
228                 
229                 float circleRadius = mHoleRadius + mDiagonalDist / 2f;
230                 canvas.drawCircle(mCenterX, mCenterY, circleRadius, mPaintBackground);
231             }
232         }
233         
234     }
235 
236     //清空画布
237     public void drawBackground(Canvas canvas) {
238         canvas.drawColor(mSplashBgColor);
239     }
240 
241     //画多个小圆
242     public void drawCircle(Canvas canvas) {
243         //每个小圆的间隔角度
244         float rotationAngle = (float) (Math.PI*2/mCircleColors.length);
245         
246         for(int i=0; i<mCircleColors.length; i++){
247             double angle = mCurrentRotationAngle + i * rotationAngle;
248             float cx = (float) (mCenterX + mCurrentRotationRadius * Math.cos(angle));
249             float cy = (float) (mCenterY + mCurrentRotationRadius * Math.sin(angle));
250             mPaint.setColor(mCircleColors[i]);
251             canvas.drawCircle(cx, cy, mCircleRadius, mPaint);
252         }
253     }
254 
255 }

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

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3     <color name="splash_bg">#F8F6EC</color>
 4     <color name="orange">#FF9600</color>
 5     <color name="aqua">#02D1AC</color>
 6     <color name="yellow">#FFD200</color>
 7     <color name="blue">#00C6FF</color>
 8     <color name="green">#00E099</color>
 9     <color name="pink">#FF3892</color>
10     
11     <array name="splash_circle_colors">
12         <item>@color/blue</item>
13         <item>@color/green</item>
14         <item>@color/pink</item>
15         <item>@color/orange</item>
16         <item>@color/aqua</item>
17         <item>@color/yellow</item>
18     </array>
19 </resources>

 

 

注:onSizeChanged在什么时候执行呢?可看http://blog.csdn.net/jason0539/article/details/9896743

posted @ 2016-05-17 22:06  zhongyinghe  阅读(220)  评论(0)    收藏  举报