【移动开发】Android波纹动画效果实现

简介:

今天我实现一个wifi当中搜索时的动画效果,通常我们会使用多张图片进行Frame动画播放,这里我使用了Tween动画,仅对一张图片进行操作,实现了wifi扫描动画效果,有兴趣的可以看看!

效果图:

180752274.png


这里我们采用了自定义布局的方式 activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< RelativeLayout  xmlns:android = "http://schemas.android.com/apk/res/android"
     xmlns:tools = "http://schemas.android.com/tools"
     android:layout_width = "match_parent"
     android:layout_height = "match_parent"
     >
     < com.zhf.android_ripple.AnimationFrameLayout
         android:id = "@+id/search_animation_wf_main"
         android:layout_width = "fill_parent"
         android:layout_height = "fill_parent"  >
     </ com.zhf.android_ripple.AnimationFrameLayout >
     < Button
         android:id = "@+id/button1"
         android:layout_width = "wrap_content"
         android:layout_height = "wrap_content"
         android:layout_alignParentRight = "true"
         android:text = "开启波纹动画"  />
</ RelativeLayout >


AnimationFrameLayout类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package  com.zhf.android_ripple;
import  java.lang.ref.SoftReference;
import  android.content.Context;
import  android.graphics.Bitmap;
import  android.graphics.BitmapFactory;
import  android.util.AttributeSet;
import  android.util.Log;
import  android.view.LayoutInflater;
import  android.view.View;
import  android.view.animation.AccelerateDecelerateInterpolator;
import  android.view.animation.AlphaAnimation;
import  android.view.animation.Animation;
import  android.view.animation.Animation.AnimationListener;
import  android.view.animation.AnimationSet;
import  android.view.animation.ScaleAnimation;
import  android.widget.FrameLayout;
import  android.widget.ImageView;
public  class  AnimationFrameLayout  extends  FrameLayout {
     private  SoftReference<Bitmap> m_bitmapRipple; //波纹图片 (软引用)
     private  ImageView[] m_imageVRadars;  //ImageView数组
                                                                                                                              
     public  AnimationFrameLayout(Context context) {
         super (context);
         init();
     }
     public  AnimationFrameLayout(Context context, AttributeSet attrs,
             int  defStyle) {
         super (context, attrs, defStyle);
         init();
     }
     public  AnimationFrameLayout(Context context, AttributeSet attrs) {
         super (context, attrs);
         init();
     }
     /**初始化**/
     private  void  init() {
         loadRadarBitmap();
         m_imageVRadars =  new  ImageView[ 3 ];
         View v = LayoutInflater.from(getContext()).inflate(R.layout.wt_search_device_anima,  this );
         m_imageVRadars[ 0 ] = (ImageView) v.findViewById(R.id.radar_ray_1);
         m_imageVRadars[ 1 ] = (ImageView) v.findViewById(R.id.radar_ray_2);
         m_imageVRadars[ 2 ] = (ImageView) v.findViewById(R.id.radar_ray_3);
     }
     /**加载图片**/
     private  void  loadRadarBitmap() {
         try  {
             //获取波纹图片
             m_bitmapRipple =  new  SoftReference<Bitmap>(BitmapFactory.decodeStream(getContext().getResources()
                             .openRawResource(R.drawable.wifi_body_ripple)));
         catch  (Exception localException) {
             Log.e( "WTSearchAnimationFrameLayout" ,
                     Log.getStackTraceString(localException));
         catch  (OutOfMemoryError localOutOfMemoryError) {
             Log.e( "WTSearchAnimationFrameLayout" ,
                     Log.getStackTraceString(localOutOfMemoryError));
             System.gc();   //回收
         }
     }
                                                                                                                              
     /**重置,停止动画**/
     public  void  stopAnimation() {
         for  ( int   i=  0 ;  i< m_imageVRadars.length; ++i) {
             if (m_bitmapRipple !=  null ){
                 Bitmap localBitmap = m_bitmapRipple.get();  //软引用获取对象
                 if (localBitmap !=  null  && !localBitmap.isRecycled()) {
                     //回收图片资源
                     localBitmap.recycle();
                 }
                 m_bitmapRipple =  null ;
                 ImageView localImageView = m_imageVRadars[i];
                 localImageView.setImageBitmap( null );  //设置ImageView为空
                 localImageView.setVisibility(View.GONE);
                 localImageView.clearAnimation();  //取消动画
             }
         }
     }
                                                                                                                              
     /**开始动画**/
     public  void  startAnimation() {
         if (m_bitmapRipple ==  null ) {
             loadRadarBitmap();
         }
         for  ( int  i =  0 ; i < m_imageVRadars.length; i++) {
             ImageView localImageView;
             long  ltime;
             while ( true ) {
                 localImageView = m_imageVRadars[i];
                 localImageView.setImageBitmap(m_bitmapRipple.get());   //获取图片
                 localImageView.setVisibility(View.VISIBLE);
                 //放大
                 ltime= 333L * i;
                 if (localImageView.getAnimation() ==  null ) {
                     break ;
                 }
                 localImageView.getAnimation().start();
             }
                                                                                                                                      
             ScaleAnimation localScaleAnimation =  new  ScaleAnimation( 1 .0f,  14 .0f, 1 .0f, 14 .0f, 1 , 0 .5f, 1 , 0 .5f);
             localScaleAnimation.setRepeatCount(- 1 );  //动画重复
             AlphaAnimation localAlphaAnimation =  new  AlphaAnimation( 1 .0f,  0 .2f);
             AnimationSet localAnimationSet =  new  AnimationSet( true );   //true:使用相同的加速器
                                                                                                                                      
             localAnimationSet.addAnimation(localScaleAnimation);
             localAnimationSet.addAnimation(localAlphaAnimation);   //将两种动画效果添加进去
             //设置相关属性
             localAnimationSet.setDuration(1000L);   //持续时间
             localAnimationSet.setFillEnabled( true );
             localAnimationSet.setFillBefore( true );   //控件保持在动画开始之前
             localAnimationSet.setStartOffset(ltime);    //动画效果推迟ltime秒钟后启动
             localAnimationSet.setInterpolator( new  AccelerateDecelerateInterpolator());
             localAnimationSet.setAnimationListener( new  MySearchAnimationHandler( this ,localImageView));  //绑定监听器
             //将动画集合设置进去
             localImageView.setAnimation(localAnimationSet);
             localImageView.startAnimation(localAnimationSet); //开启动画
         }
     }
     /**动画监听类**/
     public  class  MySearchAnimationHandler  implements  AnimationListener{
         private  ImageView m_imageVRadar;
                                                                                                                                  
         public  MySearchAnimationHandler(AnimationFrameLayout paramImageView,ImageView m_imageVRadar) {
             super ();
             this .m_imageVRadar = m_imageVRadar;
         }
         @Override
         public  void  onAnimationStart(Animation animation) {
             // TODO Auto-generated method stub
         }
         @Override
         public  void  onAnimationEnd(Animation animation) {
             this .m_imageVRadar.setVisibility(View.GONE);
         }
         @Override
         public  void  onAnimationRepeat(Animation animation) {
             animation.setStartOffset(0L);
         }
     }
}

重要说明:

1.该类中我们对图片的操作使用软引用,目的是防止OOM.

2.至于动画,使用ImageView[]来依次加载图片,通过更改对每个ImageView实现缩放和透明动画


动画布局  wt_search_device_anima.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<? xml  version = "1.0"  encoding = "utf-8" ?>
< RelativeLayout  xmlns:android = "http://schemas.android.com/apk/res/android"
     android:layout_width = "fill_parent"
     android:layout_height = "fill_parent"  >
     < ImageView
         android:id = "@+id/radar_ray_1"
         android:layout_width = "70.0dip"
         android:layout_height = "70.0dip"
         android:layout_alignParentRight = "true"
         android:layout_alignParentTop = "true"
         android:layout_marginLeft = "10.0dip"  />
     < ImageView
         android:id = "@+id/radar_ray_2"
         android:layout_width = "70.0dip"
         android:layout_height = "70.0dip"
         android:layout_alignParentRight = "true"
         android:layout_alignParentTop = "true"
         android:layout_marginLeft = "10.0dip"  />
     < ImageView
         android:id = "@+id/radar_ray_3"
         android:layout_width = "70.0dip"
         android:layout_height = "70.0dip"
         android:layout_alignParentRight = "true"
         android:layout_alignParentTop = "true"
         android:layout_marginLeft = "10.0dip"  />
</ RelativeLayout >

程序主入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package  com.zhf.android_ripple;
import  android.os.Bundle;
import  android.app.Activity;
import  android.view.View;
import  android.view.View.OnClickListener;
import  android.widget.Button;
public  class  MainActivity  extends  Activity {
                                                                   
     public  Button m_btn1;
     AnimationFrameLayout afl;  //动画布局
     @Override
     protected  void  onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
                                                                       
         afl = ((AnimationFrameLayout) findViewById(R.id.search_animation_wf_main)); // 搜索时的动画
         m_btn1 = (Button) findViewById(R.id.button1);
         m_btn1.setOnClickListener( new  OnClickListener() {
             @Override
             public  void  onClick(View v) {
                 afl.startAnimation();
             }
         });
     }
                                                                   
     @Override
     protected  void  onDestroy() {
         // TODO Auto-generated method stub
         super .onDestroy();
         afl.stopAnimation();
     }
}


ok! 源码已添加!试试效果吧!





     本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1334425,如需转载请自行联系原作者




相关文章
|
Android开发
flutter中实现仿Android端的onResume和onPause方法
flutter中实现仿Android端的onResume和onPause方法
|
缓存 JSON Java
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
java 实现读取txt文件,反射创建对象,android 手机缓存文件目录
|
Android开发 容器
Android实现面包屑效果,支持Fragment联动
Android实现面包屑效果,支持Fragment联动
|
Android开发
Android实现连线题效果
Android实现连线题效果
|
移动开发 JavaScript Android开发
通过howler.js实现在Android下的微信浏览器自动播放音频
通过howler.js实现在Android下的微信浏览器自动播放音频
741 0
通过howler.js实现在Android下的微信浏览器自动播放音频
|
存储 API Android开发
深入剖析Android四大组件(四)——Messenger实现Android IPC
深入剖析Android四大组件(四)——Messenger实现Android IPC
262 2
|
数据库 Android开发
android 多级下拉菜单实现教程 greendao使用
android 多级下拉菜单实现教程 greendao使用
android 多级下拉菜单实现教程 greendao使用
|
监控 前端开发 Java
Android自定义控件(十)——SurfaceView实战实现天气APP背景移动效果
Android自定义控件(十)——SurfaceView实战实现天气APP背景移动效果
549 0
|
XML 开发工具 Android开发
Android自定义控件(十三)——实现CSDN搜索框文字提示容器
Android自定义控件(十三)——实现CSDN搜索框文字提示容器
435 0
Android自定义控件(十三)——实现CSDN搜索框文字提示容器
|
Android开发
Android自定义控件(七)——ShapeDrawable实现放大镜效果
Android自定义控件(七)——ShapeDrawable实现放大镜效果
681 0
Android自定义控件(七)——ShapeDrawable实现放大镜效果