android中的動畫全解析

Android爲我們提供了2中動畫

一: Tween Animation 漸變動畫 通過對特定對象做圖像的變換,例如: 平移, 縮放,旋轉, 淡入淡出 等。

二: Frame Animation 幀動畫 創建一個淡入阿瓦不了可以按照指定的時間間隔一個一個顯示。順序播放

下面我們就詳細介紹一下這兩中動畫:

首先我們介紹 漸變動畫:

1. Tween Animation

1. 漸變動畫有四種樣式:

alpha: 漸變透明度

scale: 縮放尺寸伸縮動畫

translate: 移動動畫效果

rotate : 旋轉動畫

2.使用方式:

2.1 可以通過xml資源文件設置, 然後通過AnimationUtils的LoadAnimation方法加載

舉例:

alpha: 漸變透明度

<alpha android:interpolator= “@android:anim/accelerate_decelerate_interpolator”  
            android:fromAlpha="1.0"  
            android:toAlpha="0.0"  
            android:duration="3000"  
        ></alpha>   
        <!--   
    interpolator:指定一個動畫的插入器,用來控制動畫的速度變化    
        fromAlpha:動畫起始時透明度  
                      0.0表示完全透明  
                      1.0表示完全不透明  
                      以上值取0.0-1.0之間的float數據類型的數字  
        toAlpha:動畫結束時透明度  
        duration:持續時間 -->  

scale: 縮放尺寸伸縮動畫

<scale  
            android:interpolator= “@android:anim/accelerate_decelerate_interpolator”  
            android:fromXScale=”0.0″  
            android:toXScale=”1.4″  
            android:fromYScale=”0.0″  
            android:toYScale=”1.4″  
            android:pivotX=”50%”  
            android:pivotY=”50%”  
            android:fillAfter=”false”  
            android:startOffset=“700”  
            android:duration=”700″  
            android:repeatCount=”10″ />  
       <!--    
        fromXScale[float]:爲動畫起始時,X座標上的伸縮尺寸,0.0表示收縮到沒有  
        fromYScale[float]:爲動畫起始時,Y座標上的伸縮尺寸,0.0表示收縮到沒有  
                1.0表示正常無伸縮  
                值小於1.0表示收縮  
                值大於1.0表示放大  
    toXScale[float]:爲動畫結束時,X座標上的伸縮尺寸  
    toYScale[float]:爲動畫結束時,X座標上的伸縮尺寸  
    pivotX[float]:爲動畫相對於物件的X座標的開始位置  
    pivotY[float]:爲動畫相對於物件的X、Y座標的開始位置     
            50,50%,50%p。這三種寫法就分別代表了ABSOLUTE,RELATIVE_TO_SELF和RELATIVE_TO_PARENT。   
            屬性值說明:從0%-100%中取值,50%爲物件的X或Y方向座標上的中點位置  
    fillAfter[boolean]:當設置爲true ,該動畫轉化在動畫結束後被應用  
    startOffset[long]:動畫之間的時間間隔,從上次動畫停多少時間開始執行下個動畫  
    repeatCount[int]:動畫的重複次數 -->  


translate: 移動動畫效果

<translate  
    android:interpolator=”@android:anim/accelerate_decelerate_interpolator”  
    android:fromXDelta=”30″  
    android:toXDelta=”-80″  
    android:fromYDelta=”30″  
    android:toYDelta=”300″  
    android:duration=”2000″ />  
t;!--         
fromXDelta:爲動畫起始時 X座標上的位置     
toXDelta: 爲動畫結束時 X座標上的位置        
fromYDelta: 爲動畫起始時 Y座標上的位置  
toYDelta:爲動畫結束時 Y座標上的位置 -->  

rotate : 旋轉動畫

<rotate  
    android:interpolator=”@android:anim/accelerate_decelerate_interpolator”  
    android:fromDegrees=”0″  
    android:toDegrees=”+350″  
    android:pivotX=”50%”  
    android:pivotY=”50%”  
    android:duration=”3000″ />  
t;!--         
fromDegrees:動畫起始時物件的角度  
toDegrees:動畫結束時物件旋轉的角度 可以大於360度  
            當角度爲負數——表示逆時針旋轉  
            當角度爲正數——表示順時針旋轉  
            (負數from——to正數:順時針旋轉)  
            (負數from——to負數:逆時針旋轉)  
            (正數from——to正數:順時針旋轉)  
            (正數from——to負數:逆時針旋轉)  
  
pivotX;:爲動畫相對於物件的X、Y座標的開始位置  
pivotY: 爲動畫相對於物件的X、Y座標的開始位置  
            50%爲物件的X或Y方向座標上的中點位置 -->  


2.2 使用 Anmation的相關子類構造函數來初始化animation對象。

 在android的sdk中提供了想要的類,animation類派生出了    aplhaAnimation   ScaleAnimation   TranslateAnimation  RotateAnimation 分別實現了平移,旋轉,漸變,尺寸,和透明度等動畫

舉例:

//在代碼中定義 動畫實例對象
private Animation myAnimation_Alpha;
private Animation myAnimation_Scale;
private Animation myAnimation_Translate;
private Animation myAnimation_Rotate;

    //根據各自的構造方法來初始化一個實例對象
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);

myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
             Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

myAnimation_Translate = new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f);

myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
               Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
1. AlphaAnimation
AlphaAnimation類對象定義
   1. private AlphaAnimation myAnimation_Alpha;
AlphaAnimation類對象構造
AlphaAnimation(float fromAlpha, float toAlpha) 
//第一個參數fromAlpha爲 動畫開始時候透明度
//第二個參數toAlpha爲 動畫結束時候透明度
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);
//說明: 
//                0.0表示完全透明
//                1.0表示完全不透明
設置動畫持續時間
myAnimation_Alpha.setDuration(5000);
//設置時間持續時間爲 5000毫秒

2. ScaleAnimation
ScaleAnimation類對象定義

private ScaleAnimation myAnimation_Scale;
ScaleAnimation類對象構造
ScaleAnimation(float fromX, float toX, float fromY, float toY,
           int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) 
//第一個參數fromX爲動畫起始時 X座標上的伸縮尺寸    
//第二個參數toX爲動畫結束時 X座標上的伸縮尺寸     
//第三個參數fromY爲動畫起始時Y座標上的伸縮尺寸    
//第四個參數toY爲動畫結束時Y座標上的伸縮尺寸  
/*說明:
                    以上四種屬性值    
                    0.0表示收縮到沒有 
                    1.0表示正常無伸縮     
                    值小於1.0表示收縮  
                    值大於1.0表示放大
*/
//第五個參數pivotXType爲動畫在X軸相對於物件位置類型  
//第六個參數pivotXValue爲動畫相對於物件的X座標的開始位置
//第七個參數pivotXType爲動畫在Y軸相對於物件位置類型   
//第八個參數pivotYValue爲動畫相對於物件的Y座標的開始位置
myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
             Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
設置動畫持續時間
myAnimation_Scale.setDuration(700);
//設置時間持續時間爲 700毫秒
3. TranslateAnimation
ranslateAnimation類對象定義
private TranslateAnimation myAnimation_Translate;
TranslateAnimation類對象構造
TranslateAnimation(float fromXDelta, float toXDelta,
                       float fromYDelta, float toYDelta) 
//第一個參數fromXDelta爲動畫起始時 X座標上的移動位置    
//第二個參數toXDelta爲動畫結束時 X座標上的移動位置      
//第三個參數fromYDelta爲動畫起始時Y座標上的移動位置     
//第四個參數toYDelta爲動畫結束時Y座標上的移動位置
設置動畫持續時間
myAnimation_Translate = new TranslateAnimation(10f, 100f, 10f, 100f);
myAnimation_Translate.setDuration(2000);
//設置時間持續時間爲 2000毫秒

4. RotateAnimation
RotateAnimation類對象定義

private RotateAnimation myAnimation_Rotate;
RotateAnimation類對象構造
RotateAnimation(float fromDegrees, float toDegrees, 
            int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
//第一個參數fromDegrees爲動畫起始時的旋轉角度    
//第二個參數toDegrees爲動畫旋轉到的角度   
//第三個參數pivotXType爲動畫在X軸相對於物件位置類型  
//第四個參數pivotXValue爲動畫相對於物件的X座標的開始位置
//第五個參數pivotXType爲動畫在Y軸相對於物件位置類型   
//第六個參數pivotYValue爲動畫相對於物件的Y座標的開始位置
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
               Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
設置動畫持續時間
myAnimation_Rotate.setDuration(3000);
//設置時間持續時間爲 3000毫秒

如何Java代碼中使用動畫效果
使用從View父類繼承過來的方法startAnimation()來爲View或是子類View等等添加一個動畫效果
public void startAnimation (Animation animation)
view.startAnimation(myAnimation_Alpha);
view.startAnimation(myAnimation_Scale);
view.startAnimation(myAnimation_Translate);
view.startAnimation(myAnimation_Rotate);

 3: android sdk通過Interpolator 控制動畫的運行

首先要了解爲什麼需要插值器,因爲在補間動畫中,我們一般只定義關鍵幀(首幀或尾幀),然後由系統自動生成中間幀,生成中間幀的這個過程可以成爲“插值”。插值器定義了動畫變化的速率,提供不同的函數定義變化值相對於時間的變化規則,可以定義各種各樣的非線性變化函數,比如加速、減速等。下面是幾種常見的插值器:

Interpolator對象 資源ID 功能作用
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速再減速
AccelerateInterpolator @android:anim/accelerate_interpolator 加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先回退一小步然後加速前進
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 在上一個基礎上超出終點一小步再回到終點
BounceInterpolator @android:anim/bounce_interpolator 最後階段彈球效果
CycleInterpolator @android:anim/cycle_interpolator 週期運動
DecelerateInterpolator @android:anim/decelerate_interpolator 減速
LinearInterpolator @android:anim/linear_interpolator 勻速
OvershootInterpolator @android:anim/overshoot_interpolator 快速到達終點並超出一小步最後回到終點


然後我們可以這樣使用一個插值器:

<set android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
<alpha android:interpolator="@android:anim/accelerate_interpolator"
 .../>

如果只簡單地引用這些插值器還不能滿足需要的話,我們要考慮一下個性化插值器。我們可以創建一個插值器資源修改插值器的屬性,比如修改AnticipateInterpolator的加速速率,調整CycleInterpolator的循環次數等。爲了完成這種需求,我們需要創建XML資源文件,然後將其放於/res/anim下,然後再動畫元素中引用即可。我們先來看一下幾種常見的插值器可調整的屬性:
<accelerateDecelerateInterpolator> 無
<accelerateInterpolator> android:factor 浮點值,加速速率,默認爲1
<anticipateInterploator> android:tension 浮點值,起始點後退的張力、拉力數,默認爲2
<anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮點值,拉力的倍數,默認爲1.5(2  * 1.5)
<bounceInterpolator> 無
<cycleInterplolator> android:cycles 整數值,循環的個數,默認爲1
<decelerateInterpolator> android:factor 浮點值,減速的速率,默認爲1
<linearInterpolator> 無
<overshootInterpolator> 浮點值,超出終點後的張力、拉力,默認爲2
下面我們就拿最後一個插值器來舉例:

<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:tension="7.0"/>

上面的代碼中,我們把張力改爲7.0,然後將此文件命名爲my_overshoot_interpolator.xml,放置於/res/anim下,我們就可以引用到自定義的插值器了:

<scale xmlns:android="http://schemas.android.com/apk/res/android"  
    android:interpolator="@anim/my_overshoot_interpolator"  
    .../>  

如果以上這些簡單的定義還不能滿足我們的需求,那麼我們就需要考慮一下自己定義插值器類了。
我們可以實現Interpolator接口,因爲上面所有的Interpolator都實現了Interpolator接口,這個接口定義了一個方法:float getInterpolation(float input);
此方法由系統調用,input代表動畫的時間,在0和1之間,也就是開始和結束之間。
線性(勻速)插值器定義如下:

public float getInterpolation(float input) {  
    return input;  
}  
加速減速插值器定義如下:
public float getInterpolation(float input) {  
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;  
}  
有興趣的話,大家可以嘗試一下自定義一個插值器。


下面我從網上找了個相對形象的例子來介紹系統自帶的加速器,想看的就看看,不想看的完全可以跳過。


http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0110/2292.html


應用:
先來介紹一下旋轉動畫的使用,佈局文件/res/layout/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:orientation="vertical"  
  android:layout_width="fill_parent"  
  android:layout_height="fill_parent"  
  android:background="#FFFFFF">  
  <ImageView  
        android:id="@+id/piechart"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_gravity="center_horizontal"  
        android:src="@drawable/piechart"/>  
  <Button  
        android:id="@+id/positive"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="順時針"  
        android:onClick="positive"/>  
  <Button  
        android:id="@+id/negative"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="逆時針"  
        android:onClick="negative"/>       
</LinearLayout>  


我們定義了一個ImageView,用於顯示一個餅狀圖,演示旋轉動畫,然後定義了兩個按鈕,用以運行編碼實現的動畫。動畫定義文件/res/anim/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">  
    <rotate  
        android:fromDegrees="0"  
        android:toDegrees="+360"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:duration="5000"/>  
</set>  


最後再來看一下RotateActivity.java代碼:
public class RotateActivity extends Activity {  
  
    private int currAngle;  
    private View piechart;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.rotate);  
  
        piechart = findViewById(R.id.piechart);  
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);  
        piechart.startAnimation(animation);  
    }  
      
    public void positive(View v) {  
        Animation anim = new RotateAnimation(currAngle, currAngle + 180, Animation.RELATIVE_TO_SELF, 0.5f,  
                Animation.RELATIVE_TO_SELF, 0.5f);  
        /** 勻速插值器 */  
        LinearInterpolator lir = new LinearInterpolator();  
        anim.setInterpolator(lir);  
        anim.setDuration(1000);  
        /** 動畫完成後不恢復原狀 */  
        anim.setFillAfter(true);  
        currAngle += 180;  
        if (currAngle > 360) {  
            currAngle = currAngle - 360;  
        }  
        piechart.startAnimation(anim);  
    }  
      
    public void negative(View v) {  
        Animation anim = new RotateAnimation(currAngle, currAngle - 180, Animation.RELATIVE_TO_SELF, 0.5f,  
                Animation.RELATIVE_TO_SELF, 0.5f);  
        /** 勻速插值器 */  
        LinearInterpolator lir = new LinearInterpolator();  
        anim.setInterpolator(lir);  
        anim.setDuration(1000);  
        /** 動畫完成後不恢復原狀 */  
        anim.setFillAfter(true);  
        currAngle -= 180;  
        if (currAngle < -360) {  
            currAngle = currAngle + 360;  
        }  
        piechart.startAnimation(anim);  
    }  
}  



    4.動畫的運行
模式
        獨佔模式; 即程序主線程進入循環,根據動畫指令不斷刷新屏幕,直至動畫結束
        終端模式: 即有單獨一個線程時間計數,每隔一定的時間向主線程發送通知,主線程接到通知後更新屏幕。




二:Frame Animation 動畫:
    android通過AnimationDrawable來定義
    可以在xml定義,也可以使用AnimationDrawable中的API定義,由於Tween Animation與Frame Aniamtion
    有着很大的不同,因此xml定義的格式也不一樣,首先是 animation-list根節點,animation-list根節點中包含多個item子節點,每個item節點定義一幀動畫,當前幀的drawable資源和當前幀持續的時間

<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot=["true" | "false"] >  
    <item  
        android:drawable="@[package:]drawable/drawable_resource_name"  
        android:duration="integer" />  
</animation-list> 


需要注意的是:
<animation-list>元素是必須的,並且必須要作爲根元素,可以包含一或多個<item>元素;android:onshot如果定義爲true的話,此動畫只會執行一次,如果爲false則一直循環。
<item>元素代表一幀動畫,android:drawable指定此幀動畫所對應的圖片資源,android:druation代表此幀持續的時間,整數,單位爲毫秒。


我們新建一個名爲anim的工程,將四張連續的圖片分別命名爲f1.png,f2.png,f3.png,f4.png,放於drawable目錄,然後新建一個frame.xml文件:
<?xml version="1.0" encoding="utf-8"?>  
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/f1" android:duration="300" />  
    <item android:drawable="@drawable/f2" android:duration="300" />  
    <item android:drawable="@drawable/f3" android:duration="300" />  
    <item android:drawable="@drawable/f4" android:duration="300" />  
</animation-list>  


我們可以將frame.xml文件放置於drawable或anim目錄,官方文檔上是放到了drawable中了,大家可以根據喜好來放置,放在這兩個目錄都是可以運行的。


我們定義了一個ImageView作爲動畫的載體,然後定義了兩個按鈕,分別是停止和啓動動畫。
接下來介紹一下如何通過加載動畫定義文件來實現動畫的效果。我們首先會這樣寫:
 image = (ImageView) findViewById(R.id.frame_image);  
          
        image.setBackgroundResource(R.anim.frame);  
        AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
        anim.start();  


看似十分完美,跟官方文檔上寫的一樣,然而當我們運行這個程序時會發現,它只停留在第一幀,並沒有出現我們期望的動畫,也許你會失望的說一句:“Why?”,然後你把相應的代碼放在一個按鈕的點擊事件中,動畫就順利執行了,再移回到onCreate中,還是沒效果,這個時候估計你會氣急敗壞的吼一句:“What the fuck!”。但是,什麼原因呢?如何解決呢?
出現這種現象是因爲當我們在onCreate中調用AnimationDrawable的start方法時,窗口Window對象還沒有完全初始化,AnimationDrawable不能完全追加到窗口Window對象中,那麼該怎麼辦呢?我們需要把這段代碼放在onWindowFocusChanged方法中,當Activity展示給用戶時,onWindowFocusChanged方法就會被調用,我們正是在這個時候實現我們的動畫效果。當然,onWindowFocusChanged是在onCreate之後被調用的,如圖:
 @Override  
    public void onWindowFocusChanged(boolean hasFocus) {  
        super.onWindowFocusChanged(hasFocus);  
        image.setBackgroundResource(R.anim.frame);  
        AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
        anim.start();  
    }  


如果在有些場合,我們需要用純代碼方式實現一個動畫,我們可以這樣寫:
AnimationDrawable anim = new AnimationDrawable();  
for (int i = 1; i <= 4; i++) {  
    int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());  
    Drawable drawable = getResources().getDrawable(id);  
    anim.addFrame(drawable, 300);  
}  
anim.setOneShot(false);  
image.setBackgroundDrawable(anim);  
anim.start();  

學習不易,且學且珍惜。。。。。。。。


Interpolator對象 資源ID 功能作用
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速再減速
AccelerateInterpolator @android:anim/accelerate_interpolator 加速
AnticipateInterpolator @android:anim/anticipate_interpolator 先回退一小步然後加速前進
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 在上一個基礎上超出終點一小步再回到終點
BounceInterpolator @android:anim/bounce_interpolator 最後階段彈球效果
CycleInterpolator @android:anim/cycle_interpolator 週期運動
DecelerateInterpolator @android:anim/decelerate_interpolator 減速
LinearInterpolator @android:anim/linear_interpolator 勻速
OvershootInterpolator @android:anim/overshoot_interpolator 快速到達終點並超出一小步最後回到終點

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