android動畫基礎

 

一 傳統 View 動畫(Tween/Frame)

轉自:http://www.codekk.com/open-source-project-analysis/detail/Android/lightSky/%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%20Android%20%E5%8A%A8%E7%94%BB%E5%9F%BA%E7%A1%80

(抄一抄讓自己學習一下)

1.1Tween動畫

主要有 4 中:縮放、平移、漸變、旋轉,文件佈局,佈局文件必須有一個獨立的根元素,可以是 <alpha>,<scale>,<translate>, <rotate>, <set>(持有一組其它的動畫元素,甚至可以是內嵌的 set 元素) 中的一個。

1.1.1 <set>

一個持有其它動畫元素的容器 <alpha>, <scale>, <translate>,<rotate>或者其它<set> 元素

屬性
android:interpolator
應用於動畫的插值器。該值必須是一個指定了插值器資源的引用(不是一個插值器的類名),在平臺中有缺省的插值器資源可以使用,或者你可以創建自己的插值器資源,可以看下面關於插值器的討論。
android:shareInterpolator
Boolean 值, true:代表在所有的子元素中共享同一個插值器

1.1.2 <alpha>

A fade-in or fade-out animation. Represents an AlphaAnimation.一個漸入漸出的動畫,對應的 java 類爲 AlphaAnimation。

屬性
android:fromAlpha
android:toAlpha
代表動畫開始和結束時透明度,0.0 表示完全透明,1.0 表示完全不透明,Float 值

1.1.3 <scale>

可以實現動態調控件尺寸的效果,通過設置 pivotX 和 pivotY 你可以指定 image 縮放的中心點,比如:如果這些值是 0,則表示左上角,所有的縮放變化將沿着右下角的軌跡運動。對應的類爲:ScaleAnimation
屬性
android:fromXScale
android:toXScale
android:fromYScale
android:toYScale
Float 值,爲動畫起始到結束時,X、Y 座標上的伸縮尺寸
0.0 表示收縮到沒有
1.0 表示正常無伸縮

android:pivotX
android:pivotY
代表縮放的中軸點 X/Y 座標,浮點值
如果我們想表示中軸點爲圖像的中心,我們可以把兩個屬性值定義成 0.5 或者 50%。

1.1.4 <translate>

代表一個水平、垂直的位移。對應的類爲 TranslateAnimation.屬性
android:fromXDelta 屬性代表起始 X 方向的位置
android:toXDelta
android:fromYDelta
android:toYDelta

代表動畫起始或者結束 X / Y 方向上的位置,Float 或者百分比值
浮點數 num%、num%p 分別相對於自身或者父控件
如果以浮點數字表示,是一個絕對值,代表相對自身原始位置的像素值;
如果以 num%表示,代表相對於自己的百分比,比如 toXDelta 定義爲 100%就表示在 X 方向上移動自己的 1 倍距離
如果以 num%p 表示,代表相對於父類組件的百分比。

1.1.5 <rotate>

是旋轉動畫,與之對應的 Java 類是 RotateAnimation

屬性
android:fromDegrees
android:toDegrees
代表起始和結束的角度,浮點值,單位:度

android:pivotX 屬性代表旋轉中心的 X 座標值
android:pivotY 屬性代表旋轉中心的 Y 座標值
Float 值或者百分比
這兩個屬性也有三種表示方式,但是 X 軸都是相對方向都是 Left,Y 軸都是相對於 Top
浮點數、num%、num%p;
數字方式代表相對於自身左邊緣的像素值,
num%方式代表相對於自身左邊緣或頂邊緣的百分比,
num%p 方式代表相對於父容器的左邊緣或頂邊緣的百分比

屬性
android:fromDegrees
android:toDegrees
開始和結束時的弧度位置,單位是度,Float 值

調用代碼

ImageView image = (ImageView) findViewById(R.id.image);  
Animation hyperspaceJump = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump); 
image.startAnimation(hyperspaceJump);

另外,在動畫中,如果我們添加了 android:fillAfter="true"後,這個動畫執行完之後保持最後的狀態;android:duration="integer"代表動畫持續的時間,單位爲毫秒。

1.1.6 插值器

用於修改一個動畫過程中的速率,可以定義各種各樣的非線性變化函數,比如加速、減速等
在 Android 中所有的插值器都是 Interpolator 的子類,通過 android:interpolator 屬性你可以引用不同的插值器。下面是幾種插值器:

你可以通過下面的方式使用它們

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

自定義插值器如果你對系統提供的插值器不滿意,我們可以創建一個插值器資源修改插值器的屬性,比如修改 AnticipateInterpolator 的加速速率,調整 CycleInterpolator 的循環次數等。爲了完成這種需求,我們需要創建 XML 資源文件,然後將其放於/res/anim 下,然後再動畫元素中引用即可。我們先來看一下幾種常見的插值器可調整的屬性:

<?xml version="1.0" encoding="utf-8"?>  
    <InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"  
        android:attribute_name="value"  
 />

我們先來看一下幾種常見的插值器可調整的屬性:

<accelerateDecelerateInterpolator>

<accelerateInterpolator> android:factor 浮點值,加速速率,默認爲 1

<anticipateInterploator> android:tension 浮點值,起始點後退的張力、拉力數,默認爲 2

<anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮點值,拉力的倍數,默認爲 1.5(2 * 1.5)

<bounceInterpolator>

<cycleInterplolator> android:cycles int,循環的個數,默認爲 1

<decelerateInterpolator> android:factor 浮點值,減速的速率,默認爲 1

<linearInterpolator>

<overshootInterpolator> 浮點值,超出終點後的張力、拉力,默認爲 2

比如:res/anim/my_overshoot_interpolator.xml:

<?xml version="1.0" encoding="utf-8"?>  
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"  
android:tension="7.0"/>  
    This animation XML will apply the interpolator:  
    <scale xmlns:android="http://schemas.android.com/apk/res/android"  
        android:interpolator="@anim/my_overshoot_interpolator"  
        android:fromXScale="1.0"  
        android:toXScale="3.0"  
        android:fromYScale="1.0"  
        android:toYScale="3.0"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:duration="700" />

如果簡單的修改插值器的屬性值還不能夠滿足我們的需求,那麼就自己來通過實現 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;    
}

1.2 Frame 動畫

文件目錄:res/drawable/filename.xml
編譯資源數據類型 AnimationDrawable
資源引用:
Java: R.drawable.filename
XML: @[package:]drawable.filename

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

1.2.1 <animation-list>

必須作爲根元素,包含一個或者多個根元素
屬性:android:oneshot :true:只執行一次動畫,false:循環執行

1.2.2 <item>

A single frame of animation. Must be a child of a<animation-list> element.一幀獨立動畫,必須是 <animation-list>的子元素

屬性
android:drawable
Drawable 資源,用於這一幀的圖片
android:duration
Integer 類型.該幀的時長,單位爲毫秒 milliseconds.

res/anim/rocket.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/rocket_thrust1" android:duration="200" />  
            <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />  
            <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />  
        </animation-list>

調用代碼

ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);  
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);  
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();  
rocketAnimation.start();

有個問題要注意一下,當將這段代碼放在onCreat裏面的時候卻沒有動畫效果,這是因爲剛開始的時候窗口Window對象還沒有完全初始化,AnimationDrawable不能完全追加到窗口Window對象中,不仿試試將它放在onWindowsFoucsChanged()方法中。

二. Property Animation

Property Animation 動畫有兩個步聚:
1.計算屬性值
2.爲目標對象的屬性設置屬性值,即應用和刷新動畫

2.1.1 計算屬性值

過程一:計算已完成動畫分數 elapsed fraction爲了執行一個動畫,你需要創建一個 ValueAnimator,並且指定目標對象屬性的開始、結束值和持續時間。在調用 start 後的整個動畫過程中, ValueAnimator 會根據已經完成的動畫時間計算得到一個 0 到 1 之間的分數,代表該動畫的已完成動畫百分比。0 表示 0%,1 表示 100%。

過程二:計算插值(動畫變化率)interpolated fraction當 ValueAnimator 計算完已完成動畫分數後,它會調用當前設置的 TimeInterpolator,去計算得到一個 interpolated(插值)分數,在計算過程中,已完成動畫百分比會被加入到新的插值計算中。

過程三:計算屬性值當插值分數計算完成後,ValueAnimator 會根據插值分數調用合適的 TypeEvaluator 去計算運動中的屬性值。
以上分析引入了兩個概念:已完成動畫分數(elapsed fraction)、插值分數( interpolated fraction )。

2.2 核心類

2.2.1 Interpolators

插值器:時間的函數,定義了動畫的變化律。
插值器只需實現一個方法:getInterpolation(float input),其作用就是把 0 到 1 的 elapsed fraction 變化映射到另一個 interpolated fraction。 Interpolator 接口的直接繼承自TimeInterpolator,內部沒有任何方法,而TimeInterpolator只有一個getInterpolation方法,所以所有的插值器只需實現getInterpolation方法即可。
傳入參數是正常執行動畫的時間點,返回值是調用者真正想要它執行的時間點。傳入參數是{0,1},返回值一般也是{0,1}。{0,1}表示整段動畫的過程。中間的 0.2、0.3 等小數表示在整個動畫(原本是勻速的)中的位置,其實就是一個比值。如果返回值是負數,會沿着相反的方向執行。如果返回的是大於 1,會超出正方向執行。也就是說,動畫可能在你指定的值上下波動,大多數情況下是在指定值的範圍內。
getInterpolation(float input)改變了默認動畫的時間點 elapsed fraction,根據時間點 interpolated fraction 得到的是與默認時間點不同的屬性值,插值器的原理就是通過改變實際執行動畫的時間點,提前或延遲默認動畫的時間點來達到加速/減速的效果。動畫插值器目前都只是對動畫執行過程的時間進行修飾,並沒有對軌跡進行修飾。

簡單點解釋這個方法,就是當要執行 input 的時間時,通過 Interpolator 計算返回另外一個時間點,讓系統執行另外一個時間的動畫效果。

2.2.2 Evaluators

Evaluators 告訴屬性動畫系統如何去計算一個屬性值。它們通過 Animator 提供的動畫的起始和結束值去計算一個動畫的屬性值。屬性系統提供了以下幾種 Evaluators:1.IntEvaluator
2.FloatEvaluator
3.ArgbEvaluator
這三個由系統提供,分別用於計算 int,float,color 型(十六進制)屬性的計算器
4.TypeEvaluator
一個用於用戶自定義計算器的接口,如果你的對象屬性值類型,不是 int,float,或者 color 類型,你必須實現這個接口,去定義自己的數據類型。

TypeEvaluator接口只有一個方法,就是evaluate()方法,它允許你使用的 animator 返回一個當前動畫點的屬性值。

TimeInterpolator 和 TypeEvaluator 的區別
首先明確動畫屬性值的計算包括三步,其中第二步和第三步分別需要藉助TimeInterpolatorTypeEvluator完成。

TypeEvaluator所做的是根據數據結構計算最終的屬性值,允許你定義自己的數據結構,這是官方對它的真正定義,如果你所定義的屬性值的數據類型不是 float、int、color 類型,那麼你需要實現 TypeEvaluator 接口的evaluate()方法,自己進行屬性值的計算

Interpolator更傾向於你定義一種運動的變化率,比如勻速、加速、減速等,官方對 Interpolator 的定義也確實是這樣的:

A time interpolator defines the rate of change of an >animation. This allows animations to have non-linear >motion, such as acceleration and deceleration.

對於自定義高級動畫時,弄清TimeInterpolatorTypeEvaluator非常重要,如果你希望要自定義自己的動畫,那麼這兩個函數肯定是關鍵部分,一個是定義動畫變化率,一個是定義數據結構和屬性值計算方式,兩者共同決定了一個動畫的運動。

2.2.3 ValueAnimator

屬性動畫中的主要的時序引擎,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。包含了所有計算動畫值的核心函數。也包含了每一個動畫時間上的細節,信息,一個動畫是否重複,是否監聽更新事件等,並且還可以設置自定義的計算類型。

使用 ValueAnimator 實現動畫需要手動更新:

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.i("update", ((Float) animation.getAnimatedValue()).toString());
    }
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();

2.2.4 ObjectAnimator

繼承自ValueAnimator,允許你指定要進行動畫的對象以及該對象的一個屬性。該類會根據計算得到的新值自動更新屬性。也就是說上 Property Animation 的兩個步驟都實現了。大多數的情況,你使用ObjectAnimator就足夠了,因爲它使得目標對象動畫值的處理過程變得簡單,不用再向ValueAnimator那樣自己寫動畫更新的邏輯。但ObjectAnimator有一定的限制,比如它需要目標對象的屬性提供指定的處理方法,這個時候你需要根據自己的需求在ObjectAnimatorValueAnimator中做個選擇了,看哪種實現更簡便。

ObjectAnimator的自動更新功能,依賴於屬性身上的settergetter方法,所以爲了讓ObjectAnimator能夠正確的更新屬性值,你必須遵從以下規範:

  1. 該對象的屬性必須有getset方法(方法的格式必須是駝峯式),方法格式爲 set(),因爲 ObjectAnimator 會自動更新屬性,它必須能夠訪問到屬性的setter方法,比如屬性名爲foo,你就需要一個setFoo()方法,如果 setter 方法不存在,你有三種選擇:
    a.添加 setter 方法
    b.使用包裝類。通過該包裝類通過一個有效的 setter 方法獲取或者改變屬性值的方法,然後應用於原始對象,比如 NOA 的AnimatorProxy
    c.使用 ValueAnimator 代替

(這 3 點的意思總結起來就是一定要有一個setter方法,讓ObjectAnimator能夠訪問到)

  1. 如果你爲 ObjectAnimator 的工廠方法的可變參數只傳遞了一個值,那麼會被作爲動畫的結束值。

  2. 注意,屬性的getter方法和setter方法必須必須是相對應的,比如你構造了一個如下的ObjectAnimator,那麼gettersetter方法就應該爲:

    targetObject.setPropName(float) 和 targetObject.getPropName(float) :
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
  3. 根據動畫的目標屬性或者對象不同,你可能需要調用某一個 View 的invalidate方法,根據新的動畫值去強制屏幕重繪該 View。可以在onAnimateonUpdate()回調方法中去做。比如,對一個 Drawable 的顏色屬性進行動畫,只有當對象重繪自身的時候,纔會導致該屬性的更新,(不像平移或者縮放那樣是實時的)。一個 View 的所有 setter 屬性方法,比如setAlpha()setTranslationX()都可以適當的更新 View。因此你不需要在重繪的時候爲這些方法傳遞新的值。更多關於 Listener 的信息,可以參考第四部分 Animation Listeners。

簡單總結下:當你不希望向外暴露Setter方法的時候,或者希望獲取到動畫值統一做處理的話,亦或只需要一個簡單的時序機制(擁有動畫的各種值)的話,那麼你可以選擇使用ValueAnimator,它更簡單。如果你就是希望更新動畫,爲了簡便,可以使用ObjectAnimator,但自定義的屬性必須有settergetter方法,並且它們必須都是標準的駝峯式(確保內部能夠調用),必須有結束值。你可以實現Animator.AnimatorListener接口根據自己的需求去更新 View。

2.2.5 AnimatorSet

提供組合動畫能力的類。並可設置組中動畫的時序關係,如同時播放、有序播放或延遲播放。Elevator會告訴屬性動畫系統如何計算一個屬性的值,它們會從Animator類中獲取時序數據,比如開始和結束值,並依據這些數據計算動畫的屬性值。


2.2.5 AnimatorSet

提供組合動畫能力的類。並可設置組中動畫的時序關係,如同時播放、有序播放或延遲播放。Elevator會告訴屬性動畫系統如何計算一個屬性的值,它們會從Animator類中獲取時序數據,比如開始和結束值,並依據這些數據計算動畫的屬性值。

小結:TypeEvaluator
定義了屬性值的計算方式,有 int,float,color 類型,根據屬性的開始、結束值和插值一起計算出當前時間的屬性值,終極方法,整個動畫屬性值計算過程的結尾。

TimeInterpolation
插值器都必須實現的接口,定義了動畫的變化率,如線性,非線性。

ValueAnimatorObjectAnimator
兩者都可以進行屬性動畫,但是ObjectAnimator更加簡單,不用去做更新屬性值的計算,但是必須要提供標準的settergetter方法,讓ObjectAnimator能夠獲取和更新屬性值。

2.2.6 ViewPropertyAnimator

可以方便的爲某個 View 的多個屬性添加並行的動畫,只使用一個ViewPropertyAnimator對象就可以完成。它的行爲更像一個ObjectAnimator,因爲它修改的是對象的實際屬性值。但它爲一次性給多個屬性添加動畫提供了方便,而且使用ViewPropertyAnimator的代碼更連貫更易讀。
下面的代碼段分別展示了使用多個ObjectAnimator對象、一個ObjectAnimator對象、 ViewPropertyAnimator同時爲一個 View 的 X 和 Y 屬性添加動畫的示例:

多個 ObjectAnimator 結合 AnimatorSet 實現

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

一個 ObjectAnimator 結合多個 PropertyValuesHolder 實現

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

ViewPropertyAnimator: 只需一行代碼

myView.animate().x(50f).y(100f);//myView.animate()直接返回一個 ViewPropertyAnimator 對象

2.2.7 PropertyValuesHolder

顧名思義,該類持有屬性,相關屬性值的操作以及屬性的 setter,getter 方法的創建,屬性值以 Keyframe 來承載,最終由 KeyframeSet 統一處理。

2.2.8 KeyFrame

一個keyframe對象由一對 time / value 的鍵值對組成,可以爲動畫定義某一特定時間的特定狀態。
每個keyframe可以擁有自己的插值器,用於控制前一幀和當前幀的時間間隔間內的動畫。

Keyframe.ofFloat(0f,0f);第一個參數爲:要執行該幀動畫的時間節點(elapsed time / duration)
第二個參數爲屬性值。
因此如果你想指定某一特定時間的特定狀態,那麼簡單的使用 ObjectAnimator就滿足不了你了,因爲,ObjectAnimator.ofInt(....)類似的工廠方法,無法指定特定的時間點的狀態。

每個 KeyFrame 的 Interpolator
每個KeyFrame其實也有個Interpolator。如果沒有設置,默認是線性的。之前爲Animator設置的Interpolator是整個動畫的,而系統允許你爲每一KeyFrame的單獨定義Interpolator,系統這樣做的目的是允許你在某一個keyFrame做特殊的處理,也就是整體上是按照你的插值函數來計算,但是,如果你希望某個或某些KeyFrame會有不同的動畫表現,那麼你可以爲這個keyFrame設置Interpolator

因此,Keyframe 的定製性更高,你如果想精確控制某一個時間點的動畫值及其運動規律,你可以自己創建特定的 Keyframe

Keyframe 使用
爲了實例化一個keyframe對象,你必須使用某一個工廠方法:ofInt(), ofFloat(), or ofObject() 去獲取合適的keyframe類型,然後你調用ofKeyframe工廠方法去獲取一個PropertyValuesHolder對象,一旦你擁有了該對象,你可以將 PropertyValuesHolder 作爲參數獲取一個Animator,如下:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);//動畫屬性名,可變參數
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000);

2.2.9 KeyFrameSet

根據 Animator 傳入的值,爲當前動畫創建一個特定類型的 KeyFrame 集合。 通常通過 ObjectAnimator.ofFloat(...)進行賦值時,這些值其實是通過一個 KeyFrameSet 來維護的 比如:

ObjectAnimator.ofFloat(target, "translateX", 50, 100, 200);

調用者傳入的 values 爲 50,100,200,則 numKeyframs = 3,那麼創建出相應的 Keyframe 爲:Keyframe(0,50),Keyframe(1/2,100),Keyframe(1,200), 時間點 0,1/2,1 都是按比例劃分的

    public static KeyframeSet ofFloat(float... values) {
        int numKeyframes = values.length;
        FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
        if (numKeyframes == 1) {
            keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
            keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
        } else {
            keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
            for (int i = 1; i < numKeyframes; ++i) {
                keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);//這裏是關鍵
            }
        }
        return new FloatKeyframeSet(keyframes);
    }
 

2.3 在 XML 中聲明屬性動畫

通過在 XML 中定義的動畫,可以很方便的在多個 Activities 中重用而且更容易編輯,複用性強。爲了區分新的屬性動畫,從 3.1 開始,你應res/animator/下存放屬性動畫的資源文件,使用animator文件夾是可選的,但是如果你想在 Eclipse ADT 插件中使用佈局編輯工具(ADT 11.0.0+),就必須在res/animator文件夾下存放了,因爲 ADT 只會查找res/animator文件夾下的屬性動畫資源文件。

屬性動畫支持的 Tag 有
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.anim.property_animator);
set.setTarget(myObject);
set.start();

目錄res/animator/filename.xm

編譯後的資源爲
ValueAnimator, ObjectAnimator, or AnimatorSet 

XML 文件的根元素必須爲<set>,<objectAnimator>, or <valueAnimator>之一。也可以在一個 set 中組織不同的動畫,包含其它<set>元素,也就是說,可以嵌套。

<set  
  android:ordering=["together" | "sequentially"]>  

    <objectAnimator  
        android:propertyName="string"  
        android:duration="int"  
        android:valueFrom="float | int | color"  
        android:valueTo="float | int | color"  
        android:startOffset="int"  
        android:repeatCount="int"  
        android:repeatMode=["repeat" | "reverse"]  
        android:valueType=["intType" | "floatType"]/>  

    <animator  
        android:duration="int"  
        android:valueFrom="float | int | color"  
        android:valueTo="float | int | color"  
        android:startOffset="int"  
        android:repeatCount="int"  
        android:repeatMode=["repeat" | "reverse"]  
        android:valueType=["intType" | "floatType"]/>  

    <set>  
        ...  
    </set>  
</set>

2.3.2.1 <set>

動畫集合節點,有一個屬性 ordering,表示它的子動畫啓動方式是先後有序的還是同時。

屬性
sequentially:動畫按照先後順序
together (default) :動畫同時啓動

2.3.2.2 <objectAnimator>

一個對象的一個屬性,相應的 Java 類爲:ObjectAnimator

屬性
android:propertyName:
String 類型,必須要設定的值,代表要執行動畫的屬性,通過名字引用,比如你可以指定了一個 View 的"alpha" 或者 "backgroundColor",這個 objectAnimator 元素沒有暴露 target 屬性,因此不能夠在 XML 中執行一個動畫,必須通過調用loadAnimator() 填充你的 XML 動畫資源,並且調用setTarget() 應用到擁有這個屬性的目標對象上。

android:valueTo
Float、int 或者 color,也是必須值,表明了動畫結束的點,顏色由 6 位十六進制的數字表示。

android:valueFrom
相對應 valueTo,動畫的起始點,如果沒有指定,系統會通過屬性身上的 get 方法獲取,顏色也是 6 位十六進制的數字表示。

android:duration
動畫的時長,int 類型,以毫秒爲單位,默認爲 300 毫秒。

android:startOffset
動畫延遲的時間,從調用 start 方法後開始計算,int 型,毫秒爲單位,

android:repeatCount
一個動畫的重複次數,int 型,”-1“表示無限循環,”1“表示動畫在第一次執行完成後重複執行一次,也就是兩次,默認爲 0,不重複執行。

android:repeatMode
重複模式:int 型,當一個動畫執行完的時候應該如何處理。該值必須是正數或者是 -1,
“reverse”
會使得按照動畫向相反的方向執行,可實現類似鐘擺效果。
“repeat”
會使得動畫每次都從頭開始循環。

android:valueType
關鍵參數,如果該 value 是一個顏色,那麼就不需要指定,因爲動畫框架會自動的處理顏色值。有 intType 和 floatType 兩種:分別說明動畫值爲 int 和 float 型。

2.3.2.3 <animator>

在一個特定的時間裏執行一個動畫。相對應的是 ValueAnimator.所有的屬性和一樣android:valueTo
android:valueFrom
android:duration
android:startOffset
android:repeatCount
android:repeatMode
android:valueType
Value Description
floatType (default)

res/animator/property_animator.xml:

<set android:ordering="sequentially">  
    <set>  
        <objectAnimator  
            android:propertyName="x"  
            android:duration="500"  
            android:valueTo="400"  
            android:valueType="intType"/>  
        <objectAnimator  
            android:propertyName="y"  
            android:duration="500"  
            android:valueTo="300"  
            android:valueType="intType"/>  
    </set>  
    <objectAnimator  
        android:propertyName="alpha"  
        android:duration="500"  
        android:valueTo="1f"/>  
</set>

爲了執行該動畫,必須在代碼中將該動畫資源文件填充爲一個 AnimationSet 對象,然後在執行動畫前,爲目標對象設置所有的動畫集合。
簡便的方法就是通過 setTarget 方法爲目標對象設置動畫集合,代碼如下:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,  
   R.anim.property_animator);  
set.setTarget(myObject);  
set.start();

三 View anim 與 property anim 的比較

View anim 系統

view animation system 提供的能力只能夠爲 View 添加動畫。因此如果你想爲非 View 對象添加動畫,就必須自己去實現,view animation system 在 View 動畫的展現方面也是有約束的,只暴露了 View 的很少方面。比如 View 支持縮放和旋轉,但不支持背景顏色的動畫。
view animation system 的另一劣勢是,其改變的是 View 的繪製效果,真正的 View 的屬性保持不變,比如無論你在對話中如何縮放 Button 的大小,Button 的有效點擊區域還是沒有應用到動畫時的區域,其位置與大小都不變。
但是 View animation system 只需花費很少時間創建而且只需很少的代碼。如果 View 動畫完成了你所有的動作,或者你存在的代碼已經達到了你想要的效果,就沒必要使用 property 動畫系統了。

property anim 系統

完全彌補了 View anim System 的缺陷,你可以爲一個對象的任何屬性添加動畫,(View 或者非 View),同時對象自己也會被修改。並且當屬性變化的時候,property Anim 系統會自動的刷新屏幕。
屬性動畫系統在處理動畫方面也更加強勁。更高級的,你可以指定動畫的屬性,比如顏色,位置,大小,定義動畫的插值器並且同步多個動畫。
並且在 Property Animation 中,改變的是對象的實際屬性,如 Button 的縮放,Button 的位置與大小屬性值都改變了。而且 Property Animation 不止可以應用於 View,還可以應用於任何對象。

平時使用的簡單動畫特效,使用 View 動畫就可以滿足,但是如果你想做的更加複雜,比如背景色的動畫,或者不僅是 View,還希望對其它對象添加動畫等,那麼你就得考慮使用 Property 動畫了。

更多動畫開源庫及使用,可以參考個人博客:Android 動畫系列,其中介紹了一些基本使用,也提到了一些 GitHub 上的動畫開源庫,可以作爲 Android 動畫學習的資料


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