【移動開發】Android波紋動畫效果實現

今天我實現一個wifi當中搜索時的動畫效果,通常我們會使用多張圖片進行Frame動畫播放,這裏我使用了Tween動畫,僅對一張圖片進行操作,實現了wifi掃描動畫效果,有興趣的可以看看!

效果圖:

180752274.png


這裏我們採用了自定義佈局的方式 activity_main.xml

<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類:

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

<?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>

程序主入口:

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! 源碼已添加!試試效果吧!






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章