1. 程式人生 > >Android動畫解析(一)-----逐幀動畫和補間動畫

Android動畫解析(一)-----逐幀動畫和補間動畫

今天專案又用到了動畫,發現之前掌握的那些又遺忘了不少,趁著有時間,再重新捋順一邊。

Android中的動畫分為 逐幀動畫,補間動畫,屬性動畫 三種.

逐幀動畫(Frame Animation)

逐幀動畫:就像GIF圖片一樣,通過一系列的Drawable依次顯示來模擬動畫效果。

  • 使用方式:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/pic1"
android:duration="150" />
<item android:drawable="@drawable/pic2" android:duration="150" /> <item android:drawable="@drawable/pic3" android:duration="150" /> </animation-list> <!--XML檔案以<animation-list>為根元素, 以<item>表示要輪換顯示的圖片, oneshot屬性,用於設定播放模式(是單次播放還是迴圈播放) duration屬性表示各項顯示的時間。 XML檔案要放在/res/drawable/目錄下-->
  • 呼叫方法:
 AnimationDrawable animationDrawable = (AnimationDrawable) loadingImage.getDrawable();
 animationDrawable.start();//開始動畫
 animationDrawable.stop();//結束動畫

補間動畫(Tween Animation)

補間動畫:給出兩個關鍵幀,通過一些演算法將給定屬性值在給定的時間內在兩個關鍵幀間漸變。
補間動畫是使用Animation類建立的,下面的列表說明了四種可用的動畫型別:

動畫型別 簡介
AlphaAnimation 可以改變View的透明度。(透明度漸變動畫)
ScaleAnimation 允許縮放選中的View。(縮放動畫)
RotateAnimation 可以在XY平面上旋轉選中的View。(旋轉動畫)
TranslateAnimation 可以在螢幕上移動選中的View。(平移動畫)

當View設定補件動畫後,動畫只是移動了內容,View本身其實還在原地,所以點選事件也還是在原地,如果想讓點選事件跟著移動,最簡單的是使用屬性動畫。

TranslateAnimation(平移動畫)

java程式碼寫法
TranslateAnimation 
animation = new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);

// fromXDelta 屬性為動畫起始時 X座標上的位置    toXDelta   屬性為動畫結束時 X座標上的位置
// fromYDelta 屬性為動畫起始時 Y座標上的位置    toYDelta   屬性為動畫結束時 Y座標上的位置
//  沒有指定fromXType toXType fromYType toYType 時候, 預設是以自己為相對參照物       

...
View.startAnimation(animation);
XML檔案寫法

通過配置XML檔案來實現平移動畫,檔案需要放在res\anim目錄中,在動畫檔案中通過<translate>標籤設定移動效果。首先在res\anim目錄下建一個動畫檔案

translate_tween.xml,該檔案的內容如下:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"  
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/accelerate_interpolator"   
    android:toXDelta="60"
    android:toYDelta="60" >

</translate>
<!-- android:interpolator     動畫差值器-->
<!-- android:duration        動畫持續時間,以毫秒為單位 -->
<!-- android:fillAfter       如果設定為true,控制元件動畫結束時,將保持動畫最後時的狀態-->
<!-- android:fillBefore      如果設定為true,控制元件動畫結束時,還原到開始動畫前的狀態-->
<!-- android:fillEnabled     與android:fillBefore 效果相同,都是在動畫結束時,將控制元件還原到初始化狀態-->
<!-- android:repeatCount     重複次數-->
<!-- android:repeatMode      重複型別,有reverse和restart兩個值,reverse表示倒序回放,restart表示重新放一遍,必須與repeatCount一起使用才能看到效果。因為這裡的意義是重複的型別,即回放時的動作。-->
// 在程式碼中這樣呼叫
Animation animation=AnimationUtils.loadAnimation(this, R.anim.translate_tween);
View.startAnimation(animation);

或者用這種方式
//View.setAnimation(animation);
//animation.start();
TranslateAnimation特有屬性

 * android:fromXDelta="0%"   動畫開始執行時X軸方向控制元件的起始位置,
                    * 當value加%時(例如80%),意思是相對於控制元件的原始位置往右的80%控件寬度的位置  
                    * 又例如value為-20%時,意思是相對於控制元件的原始位置往左的20%控件寬度的位置。
                    * 當Value不加%時(例如80),表示相對於控制元件的原始位置往右80個畫素(px)的位置,
                    * 又如當Value為-20時,即往左20個畫素。  

* android:toXDelta="100%"動畫結束執行時X軸方向控制元件的結束位置,Value可以加%,也可以不加%,原理同上  
* android:fromYDelta="0%"動畫開始執行時Y軸方向控制元件的起始位置,Value可以加%,也可以不加%,原理同上  
* android:toYDelta="100%"動畫結束執行時Y軸方向控制元件的結束位置,Value可以加%,也可以不加%,原理同上  

AlphaAnimation(透明度漸變動畫)

Java程式碼寫法
 AlphaAnimation mAlphaAnimation = new AlphaAnimation(float fromAlpha, float toAlpha);
 //fromAlpha:設定動畫開始時控制元件的透明度
  //toAlpha:設定動畫結束時的控制元件的透明度 
  //兩個值取值都為0~1之間,0.0為透明,控制元件不顯示,1.0為不透明,控制元件全部顯示 
  ...
  View.startAnimation(mAlphaAnimation);
XML寫法

同樣檔案需要放在res\anim目錄中,在動畫檔案中通過<alpha>標籤設定漸變效果。首先在res\anim目錄下建一個動畫檔案
alpha_tween.xml,該檔案的內容如下:

<alpha xmlns:android="http://schemas.android.com/apk/res/android"  
        android:fromAlpha= "0.0"  
        android:toAlpha= "1.0"  
        >  
</alpha>  
<!-- android:interpolator     動畫差值器-->
<!-- android:duration        動畫持續時間,以毫秒為單位 -->
<!-- android:fillAfter       如果設定為true,控制元件動畫結束時,將保持動畫最後時的狀態-->
<!-- android:fillBefore      如果設定為true,控制元件動畫結束時,還原到開始動畫前的狀態-->
<!-- android:fillEnabled     與android:fillBefore 效果相同,都是在動畫結束時,將控制元件還原到初始化狀態-->
<!-- android:repeatCount     重複次數-->
<!-- android:repeatMode      重複型別,有reverse和restart兩個值,reverse表示倒序回放,restart表示重新放一遍,必須與repeatCount一起使用才能看到效果。因為這裡的意義是重複的型別,即回放時的動作。-->
// 在程式碼中這樣呼叫
Animation animation=AnimationUtils.loadAnimation(this, R.anim.alpha_tween);
View.startAnimation(animation);

或者用這種方式
//View.setAnimation(animation);
//animation.start();
AlphaAnimation特有屬性
android:fromAlpha:動畫開始時的透明度,變化範圍為0.0-1.0,0.0表示完全透明,1.0表示完全不透明
android:toAlpha:動畫結束是的透明度,變化範圍和意義同上。

RotateAnimation(旋轉動畫)

Java程式碼寫法
RotateAnimation mRotateAnimation =  new RotateAnimation(float fromDegrees, float toDegrees,  
             int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);

// android:fromDegrees :動畫開始時旋轉的角度位置,float型別,正值代表順時針方向度數,負值程式碼逆時針方向度數
//android:toDegrees : 動畫結束時旋轉到的角度位置,float型別,正值代表順時針方向度數,負值程式碼逆時針方向度數

//android:pivotXType: 確定動畫在X軸的中心位置型別。與下面的pivotXValue結合,確定X軸上旋轉中心。(取值見下表)

//android:pivotXValue  :旋轉點X軸座標值,float型別,可以是數值、百分數、百分數p三種樣式,比如50、50%、50%p
                        //當為數值時,表示在當前View的左上角,即原點處加上50px,做為旋轉點X座標,
                        //如果是50%;表示在當前控制元件的左上角加上自己寬度的50%做為旋轉點X座標;
                        //如果是50%p,那麼就是表示在當前控制元件的左上角加上父控制元件寬度的50%做為旋轉點X座標。

//android:pivotYType: 確定動畫在Y軸的中心位置型別。取值及意義跟android:pivotXType一樣。
//android:pivotYValue:旋轉點Y軸座標值,取值及意義跟android:pivotX一樣。

...
View.startAnimation(mRotateAnimation);
pivotXType值 效果
Animation.ABSOLUTE 預設值,圍繞設定動畫控制元件的左上角旋轉與pivotXValue = 0,pivotYVaule = 0效果相同
Animation.RELATIVE_TO_PARENT 設定動畫控制元件的左上角為座標原點(0,0),動畫旋轉軸的座標為(parent.getWidth*pivotXValue,parent.getHeight*pivotYValue)[parent為view的父控制元件]負數向左(X軸)/上(Y軸)偏移,正數向右(X軸)/下(Y軸)偏移;
Animation.RELATIVE_TO_SELF 設定動畫控制元件的左上角為座標原點(0,0),動畫旋轉軸的座標為(view.getWidth*pivotXValue,view.getHeight*pivotYValue)負數向左(X軸)/上(Y軸)偏移,正數向右(X軸)/下(Y軸)偏移;
XML檔案寫法

在res\anim目錄下建一個動畫檔案rotate_tween.xml,該檔案的內容如下:

    <?xml version="1.0" encoding= "utf-8"?>  
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"  
             android:fromDegrees= "0"  
             android:toDegrees= "360"  
             android:pivotX= "50%"  
             android:pivotY= "50%"  
             >  
    </rotate>  
<!-- android:interpolator=     動畫差值器-->
<!-- android:duration        動畫持續時間,以毫秒為單位 -->
<!-- android:fillAfter       如果設定為true,控制元件動畫結束時,將保持動畫最後時的狀態-->
<!-- android:fillBefore      如果設定為true,控制元件動畫結束時,還原到開始動畫前的狀態-->
<!-- android:fillEnabled     與android:fillBefore 效果相同,都是在動畫結束時,將控制元件還原到初始化狀態-->
<!-- android:repeatCount     重複次數-->
<!-- android:repeatMode      重複型別,有reverse和restart兩個值,reverse表示倒序回放,restart表示重新放一遍,必須與repeatCount一起使用才能看到效果。因為這裡的意義是重複的型別,即回放時的動作。-->
// 在程式碼中這樣呼叫
Animation animation=AnimationUtils.loadAnimation(this, R.anim.rotate_tween);
View.startAnimation(animation);

或者用這種方式
//View.setAnimation(animation);
//animation.start();
RotateAnimation特有屬性
android:fromDegrees:動畫開始時旋轉的角度位置,float型別,正值代表順時針方向度數,負值程式碼逆時針方向度數
android:toDegrees: 動畫結束時旋轉到的角度位置,float型別,正值代表順時針方向度數,負值程式碼逆時針方向度數
android:pivotX:旋轉點X軸座標,float型別,可以是數值、百分數、百分數p三種樣式,比如5050%、50%p,當為數值時,表示在當前View的左上角,即原點處加上50px,做為旋轉點X座標,如果是50%;表示在當前控制元件的左上角加上自己寬度的50%做為旋轉點X座標;如果是50%p,那麼就是表示在當前控制元件的左上角加上父控制元件寬度的50%做為旋轉點X座標。
android:pivotY:旋轉點Y軸座標,取值及意義跟android:pivotX一樣。

ScaleAnimation(縮放動畫)

Java程式碼寫法
ScaleAnimation mScaleAnimation = ScaleAnimation(float fromX, float toX, float fromY,  
        float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);
// float fromX 動畫起始時 X座標上的伸縮尺寸 比如1.0代表自身無變化,0.5代表起始時縮小一倍,2.0代表放大一倍
// float toX 動畫結束時 X座標上的伸縮尺寸   
// float fromY 動畫起始時Y座標上的伸縮尺寸   
// float toY 動畫結束時Y座標上的伸縮尺寸   

//android:pivotXType: 確定動畫在X軸的中心位置型別。與下面的pivotXValue結合,確定X軸上縮放中心點。。(取值見下表)
// float pivotXValue 動畫相對於物件的X座標的開始位置   
// int pivotYType 動畫在Y軸相對於物件位置型別   
// float pivotYValue 動畫相對於物件的Y座標的開始位置   

...
View.startAnimation(mScaleAnimation);
pivotXType值 效果
Animation.ABSOLUTE 預設值,設定動畫控制元件從左上角縮放,與pivotXValue = 0,pivotYVaule = 0效果相同
Animation.RELATIVE_TO_PARENT 設定動畫控制元件的左上角為座標原點(0,0),動畫縮放點的座標為(parent.getWidth*pivotXValue,parent.getHeight*pivotYValue)【parent為view的父控制元件】負數向左(X軸)/上(Y軸)偏移,正數向右(X軸)/下(Y軸)偏移;
Animation.RELATIVE_TO_SELF 設定動畫控制元件的左上角為座標原點(0,0),動畫所放點的座標為(view.getWidth*pivotXValue,view.getHeight*pivotYValue)負數向左(X軸)/上(Y軸)偏移,正數向右(X軸)/下(Y軸)偏移;
XML檔案寫法
<?xml version="1.0" encoding= "utf-8"?>   
<scale xmlns:android="http://schemas.android.com/apk/res/android"  
       android:fromXScale= "2.0"  
       android:toXScale= "1.0"  
       android:fromYScale= "2.0"  
       android:toYScale= "1.0"  
       android:pivotX= "50%"  
       android:pivotY= "50%"  
       >  
</scale> 
<!-- android:interpolator=     動畫差值器-->
<!-- android:duration        動畫持續時間,以毫秒為單位 -->
<!-- android:fillAfter       如果設定為true,控制元件動畫結束時,將保持動畫最後時的狀態-->
<!-- android:fillBefore      如果設定為true,控制元件動畫結束時,還原到開始動畫前的狀態-->
<!-- android:fillEnabled     與android:fillBefore 效果相同,都是在動畫結束時,將控制元件還原到初始化狀態-->
<!-- android:repeatCount     重複次數-->
<!-- android:repeatMode      重複型別,有reverse和restart兩個值,reverse表示倒序回放,restart表示重新放一遍,必須與repeatCount一起使用才能看到效果。因為這裡的意義是重複的型別,即回放時的動作。-->
// 在程式碼中這樣呼叫
Animation animation=AnimationUtils.loadAnimation(this, R.anim.rotate_tween);
View.startAnimation(animation);

或者用這種方式
//View.setAnimation(animation);
//animation.start();
ScaleAnimation特有屬性
android:fromXScale起始的X方向上相對自身的縮放比例,型別float,比如1.0代表自身無變化,0.5代表起始時縮小一倍,2.0代表放大一倍
android:toXScale:結尾的X方向上相對自身的縮放比例,型別float
android:fromYScale:起始的Y方向上相對自身的縮放比例,型別float
android:toYScale:結尾的Y方向上相對自身的縮放比例,型別float
android:pivotX: 縮放起點X軸座標,可以是數值、百分數、百分數p ,具體意義roate中已經演示
android:pivotY:縮放起點Y軸座標,取值及意義與pivotX一樣

補間動畫設定動畫監聽事件

mAnimation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                //在動畫開始時執行處理
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //在動畫重複時執行處理
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //在動畫完成後執行處理
            }
        });

AnimationSet

AnimationSet 可以讓許多個動畫在同一時間開始(也就是動畫的疊加)
注意 : AnimationSet 和 AnimatorSet 注意區分區別,這裡只做AnimationSet講解。下篇部落格講解AnimatorSet

Java 程式碼寫法
    //建立動畫,引數表示他的子動畫是否共用一個插值器
        AnimationSet animationSet = new AnimationSet(true);
        //新增動畫(可以新增多個,每個動畫都可以單獨設定屬性)
        animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f));
        animationSet.addAnimation(new TranslateAnimation(0,120 , 0, -300));

        //設定插值器
        animationSet.setInterpolator(new LinearInterpolator());
        //設定動畫持續時長
        animationSet.setDuration(3000);
        //設定動畫結束之後是否保持動畫的目標狀態
        animationSet.setFillAfter(true);
        //設定動畫結束之後是否保持動畫開始時的狀態
        animationSet.setFillBefore(false);
        //設定重複模式
        animationSet.setRepeatMode(Animation.REVERSE);
        //設定重複次數
        animationSet.setRepeatCount(Animation.INFINITE);
        //設定動畫延時時間
        animationSet.setStartOffset(2000);
        //取消動畫
        animationSet.cancel();
        //釋放資源
        animationSet.reset();
        //開始動畫
        mIvImg.startAnimation(animationSet);
XML檔案寫法

檔案目錄:res/anim/animation_set.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:shareInterpolator="true">
    <alpha
        android:duration="2000"
        android:fillAfter="true"
        android:fillBefore="false"
        android:fromAlpha="1.0"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toAlpha="0.0"/>
    <rotate
        android:duration="2000"
        android:fillAfter="true"
        android:fillBefore="false"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toDegrees="360"/>
    <set
        android:interpolator="@android:anim/bounce_interpolator"
        android:shareInterpolator="true"
        android:startOffset="1000">
        <scale
            android:duration="2000"
            android:fillAfter="true"
            android:fillBefore="false"
            android:fromXScale="1.0"
            android:fromYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatCount="-1"
            android:repeatMode="reverse"
            android:toXScale="2.0"
            android:toYScale="2.0"/>
        <translate
            android:duration="2000"
            android:fillAfter="true"
            android:fillBefore="false"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:repeatCount="-1"
            android:repeatMode="reverse"
            android:toXDelta="200%"
            android:toYDelta="200%"/>
    </set>
</set>
Java程式碼中呼叫  
 AnimationSet animationSet = (AnimationSet)  
                AnimationUtils.loadAnimation(XmlViewAnimationActivity.this, R.anim.animation_set);
 View.startAnimation(animationSet);

差值器效果

AccelerateDecelerateInterpolator============動畫開始與結束的地方速率改變比較慢,在中間的時候加速。
AccelerateInterpolator===================動畫開始的地方速率改變比較慢,然後開始加速。
AnticipateInterpolator ==================開始的時候向後然後向前甩。
AnticipateOvershootInterpolator=============開始的時候向後然後向前甩一定值後返回最後的值。
BounceInterpolator=====================動畫結束的時候彈起。
CycleInterpolator======================動畫迴圈播放特定的次數,速率改變沿著正弦曲線。
DecelerateInterpolator===================在動畫開始的地方快然後慢。
LinearInterpolator======================以常量速率改變。
OvershootInterpolator====================向前甩一定值後再回到原來位置。
PathInterpolator========================新增的,就是可以定義路徑座標,然後可以按照路徑座標來跑動;注意其座標並不是 XY,
而是單方向,也就是我可以從0~1,然後彈回0.5 然後又彈到0.7 有到0.3,直到最後時間結束。