屬性動畫總覽

試用 Compose
Jetpack Compose 是 Android 推薦的 UI 工具包。瞭解如何在 Compose 中使用動畫。

屬性動畫系統是強大的架構 幾乎能為任何元素加入動畫您可以定義動畫,隨著時間變更任何物件屬性。 檢查是否繪製在螢幕上屬性動畫會變更屬性的 (物件中的欄位) 值。如要為內容製作動畫,請指定 要加入動畫效果的物件屬性,例如物件在畫面上的位置、 要套用動畫效果 以及要套用動畫效果的值

屬性動畫系統可讓您定義 動畫:

  • 時間長度:您可以指定動畫的時間長度。預設時間長度為 300 毫秒。
  • 時間內插:您可以指定屬性值的計算方式 動畫目前的經過時間函式。
  • 重複計數和行為:您可以指定是否要在下列情況重複播放動畫: 動畫播放時間結束,以及重複播放動畫的次數。你也可以 指定是否要反向播放動畫。設定反向播放 動畫向前快轉,直到達到重複次數為止。
  • 動畫集合:您可以將動畫組合成可一起播放的邏輯組合,或是 排序或記錄到特定延遲時間後
  • 影格重新整理延遲時間:您可以指定重新整理動畫影格的頻率。 預設設定為每 10 毫秒重新整理一次,但是應用程式重新整理影格的速度為 最終取決於系統的整體繁忙程度,以及系統可為基礎計時器服務的速度。

如要查看屬性動畫的完整範例,請參閱 CustomTransition 中的 ChangeColor 類別 範例。

屬性動畫的運作方式

首先,讓我們透過簡單的範例,說明動畫的運作方式。圖 1 描述了 以 x 屬性呈現動畫的假設物件,代表該物件 畫面上的水平位置。動畫時間長度設為 40 毫秒,距離 移動距離為 40 像素每 10 毫秒 (預設的影格刷新率) 都會移動物件一次 水平乘以 10 像素40 毫秒結束時,動畫會停止,物件則結束於 水平位置 40這個動畫範例採用線性內插類型 物件會以穩定的速度移動

圖 1. 線性動畫範例

您也可以指定動畫具有非線性內插。圖 2 說明瞭 這類物件會在動畫開始時加速,並在動畫開始時減速, 物體仍會在 40 毫秒內移動 40 像素,但並非線性移動。在 這個動畫一開始就加速至中點 直到動畫結束為止如圖 2 所示,移動的距離 出現在動畫開頭和結尾處都少於中間的長度。

圖 2. 非線性動畫範例

以下將詳細說明屬性動畫系統的重要元件 會計算與上圖所示的動畫一樣。圖 3 描述主要類別的方式 執行這些動作

圖 3. 動畫的計算方式

ValueAnimator 物件會追蹤動畫時間。 例如動畫已經播放的時間長度,以及動畫在播放時的目前值 動畫。

ValueAnimator 會封裝 TimeInterpolator (用來定義動畫內插類型) 和 TypeEvaluator,用於定義如何計算屬性的值 動畫。例如,在圖 2 中,使用的 TimeInterpolator 會是 AccelerateDecelerateInterpolatorTypeEvaluator 會是 IntEvaluator

如要開始動畫,請建立 ValueAnimator 並為其提供 加入動畫後屬性的起始值和結束值,以及 動畫。呼叫 start() 動畫時 。在整個動畫播放期間,ValueAnimator 會計算經過的分數 介於 0 到 1 之間,根據動畫長度和經過的時間。 經過的比例代表動畫播放完畢的時間百分比,0 代表 0% 1 代表 100%例如,在圖 1 中,在 t = 10 毫秒時的比率為 .25 因為總持續時間為 t = 40 ms。

ValueAnimator 計算經過的分數時, 會呼叫目前設定的 TimeInterpolator,以便計算 內插分數。內插比例會將經過的分數對應至新的 的比例。例如,在圖 2 中 因為動畫的播放速度緩慢,因此內插分數 (約 0 .15) 低於 。在圖 1 中,內插分數一律與 所花費的分數

計算內插分數時,系統會呼叫 ValueAnimator 適當的 TypeEvaluator 來計算 您要加上動畫效果的屬性,取決於內插分數、起始值和 的結束值。例如,在圖 2 中,內插分數為 0 .15,而 t = 10 毫秒,此時的屬性值會是 .15 × (40 - 0) 或 6。

屬性動畫與視圖動畫的差異

視圖動畫系統提供僅為 View 建立動畫的功能 因此,如果您想為非 View 物件建立動畫,就必須實作 導入您自己的程式碼另外,播放動畫系統也受到限制 公開 View 物件的幾個部分來製作動畫,例如縮放和 例如旋轉檢視畫面,而不是背景顏色

檢視區塊動畫系統的另一個缺點是只會在 此為繪製檢視畫面,而非實際的檢視畫面。舉例來說,如果動畫呈現在您將移動的按鈕上 此時按鈕會正確繪製,但實際點選位置時 按鈕不會變更,因此您必須實作自己的邏輯來處理這項設定。

使用屬性動畫系統時,這些限制條件會完全移除,而您可以建立動畫。 任何物件的任何屬性 (View 和非 View) 以及物件本身,都會受到修改。 屬性動畫系統執行動畫的方式也更加完善。在 高階,您可以為每個要建立動畫的屬性指派動畫,例如顏色、 位置或大小,也可以定義動畫的各個元素,例如內插和大小 以便產生多個動畫

但視圖動畫系統則能較少設定,且所需的撰寫程式碼也較少。 如果視圖動畫實現了您需要執行的所有動作,或現有程式碼是否已完成 可以達到您希望的效果,不需要使用屬性動畫系統。其他可能 如果不同用途,分別使用這兩種動畫系統即可。

API 總覽

您可以在 android.animation 中找到屬性動畫系統的大部分 API。因為視圖動畫系統 在 android.view.animation 中定義許多內插器,您可以使用 屬性動畫系統中也有這些內插器下表說明主要的 屬性動畫系統元件

Animator 類別提供建立應用程式的基本結構 動畫。您通常不會直接使用這個類別,因為它只會用到最少 才能完整支援動畫值。下列 子類別擴充 Animator

表 1. 動畫師

類別 說明
ValueAnimator 屬性動畫的主要時間引擎,也會計算 動畫屬性。具備所有用來計算動畫的核心功能 值,並包含每個動畫的時間詳細資料、 重複動畫、接收更新事件的監聽器,以及設定自訂 要評估的幾種類型為屬性加上動畫效果分為兩個部分:計算動畫 值,並在動畫的物件和屬性上設定這些值。「ValueAnimator」不會連出第二部分,所以你必須聆聽 更新 ValueAnimator 和 修改您要以自己的邏輯加入動畫的物件。請參閱 使用 ValueAnimator 製作動畫
ObjectAnimator ValueAnimator 的子類別,可讓您設定目標 物件和物件屬性建立動畫此類別會根據 就會計算動畫的新值。要使用的目標對象 大多數時間:ObjectAnimator 因為這樣可以更輕鬆地在目標物件上為值加上動畫效果。不過 由於 ObjectAnimator 還有一些限制 (例如規定必須明確限制),因此您有時候會想要直接使用 ValueAnimator 存取子方法。
AnimatorSet 提供將動畫組合成群組的機制 這兩個物件之間的關係您可以設定讓動畫依序播放、依序播放或之後播放 指定的延遲時間請參閱「Choreographing multiple 加入動畫集瞭解更多資訊

評估器會指示屬性動畫系統如何計算給定 資源。會使用 Animator 提供的時間資料 類別、動畫的開始和結束值,以及計算屬性的動畫值 根據這項資料屬性動畫系統提供下列評估器:

表 2. 評估工具

類別/介面 說明
IntEvaluator 用於計算 int 屬性值的預設評估工具。
FloatEvaluator 用於計算 float 屬性值的預設評估工具。
ArgbEvaluator 預設的評估器會計算用於表示的顏色屬性值 十六進位值。
TypeEvaluator 可讓您建立自己的評估工具的介面。如果要以動畫形式呈現 「非」intfloat 或顏色的物件屬性; 您必須實作 TypeEvaluator 介面,以指定 計算物件屬性的動畫值。您也可以為 intfloat 和顏色指定自訂 TypeEvaluator 如果您想以不同方式處理這些型別,與預設行為不同。 詳情請參閱「使用 TypeEvaluator」一節 瞭解如何編寫自訂評估器。

時間內插器會定義動畫中特定值的計算方式 時間函式。舉例來說,您可以指定在整個播放過程中以線性方式播放的動畫 也就是動畫會隨時間平均移動 非線性時間,例如從開頭加速加速, 表 3 說明 android.view.animation 內含的內插器。如果所有提供的內插器皆不適合 實作 TimeInterpolator 介面並自行建立。如要進一步瞭解如何編寫自訂,請參閱「使用內插器」 內插器。

表 3. 內插器

類別/介面 說明
AccelerateDecelerateInterpolator 內插器的變化速率開始和結束,但速度加快的內插器 中途
AccelerateInterpolator 變化速率一開始緩慢的內插器 加速發展。
AnticipateInterpolator 內插器,其變更會先從反向開始,再向前快速滑過。
AnticipateOvershootInterpolator 內插器,其變更開始反向、正向快速滑過和過度 接著回到最終值。
BounceInterpolator 變更在結尾彈跳的內插器。
CycleInterpolator 內插器的動畫會依照指定循環次數重複播放。
DecelerateInterpolator 變化速率一開始很快的內插器 減速度。
LinearInterpolator 變化速率不變的內插器。
OvershootInterpolator 此內插器的內插器往前快速滑過並超過最終值,然後 應用程式。
TimeInterpolator 可讓您實作自己的內插器介面。

使用 ValueAnimator 製作動畫

ValueAnimator 類別可讓您為 您可以指定一組 intfloat 或顏色,藉此設定動畫的時間長度 產生動畫效果您可以藉由呼叫ValueAnimator 其工廠方法:ofInt()ofFloat()ofObject()。例如:

Kotlin

ValueAnimator.ofFloat(0f, 100f).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();

在這段程式碼中,ValueAnimator 會開始計算 在 start() 方法執行時,介於 0 到 100 之間,時間長度為 1000 毫秒。

您也可以按照下列步驟指定要建立動畫的自訂類型:

Kotlin

ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply {
    duration = 1000
    start()
}

Java

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

在這段程式碼中,ValueAnimator 會開始計算 動畫,介於 startPropertyValueendPropertyValue 之間 start() 方法執行時,由 MyTypeEvaluator 提供的邏輯,持續 1000 毫秒。

只要新增 AnimatorUpdateListener 附加至 ValueAnimator 物件,如 下列程式碼:

Kotlin

ValueAnimator.ofObject(...).apply {
    ...
    addUpdateListener { updatedAnimation ->
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        textView.translationX = updatedAnimation.animatedValue as Float
    }
    ...
}

Java

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

在「onAnimationUpdate()」中 方法中,您可以存取更新後的動畫值,並將其用於 其中一項資料檢視如要進一步瞭解事件監聽器,請參閱 動畫事件監聽器

使用 ObjectAnimator 製作動畫

ObjectAnimatorValueAnimator 的子類別 (如前一節所述),並結合 引擎和價值計算ValueAnimator的功能 加上目標物件的具名屬性動畫。這樣就能更輕鬆地為任何物件建立動畫 不需要導入 ValueAnimator.AnimatorUpdateListener 因為動畫屬性會自動更新

建立 ObjectAnimator 例項與 ValueAnimator 類似,但您也可以指定該物件的物件及其屬性名稱 ( 字串) 以及其以下兩個之間動畫的值:

Kotlin

ObjectAnimator.ofFloat(textView, "translationX", 100f).apply {
    duration = 1000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();

取得 ObjectAnimator 更新屬性 就必須執行下列操作:

  • 您要建立動畫的物件屬性必須具有 setter 函式 (駝峰式大小寫),格式為 set<PropertyName>()。因為ObjectAnimator 屬性在動畫期間會自動更新,且必須可存取屬性 利用這個 setter 方法例如,如果屬性名稱為 foo,您必須 具有 setFoo() 方法如果找不到這個 setter 方法, 選項:
    • 如果您有權執行此操作,請將 setter 方法新增至類別。
    • 使用您有權變更的包裝函式類別,並讓該包裝函式接收 值,並轉送至原始物件。
    • 請改用 ValueAnimator
  • 如果您在其中一個 ObjectAnimator 工廠方法中只為 values... 參數指定一個值,系統會假設該參數為 因此,您要建立動畫的物件屬性必須有 getter 函式 用於取得動畫的起始值。getter 函式必須位於 get<PropertyName>() 形式。舉例來說,如果屬性名稱是 foo,您需要有 getFoo() 方法。
  • 您要建立動畫的屬性的 getter (如有需要) 和 setter 方法 會針對您指定 ObjectAnimator 的起始值和結束值使用相同的類型。舉例來說,您必須擁有 「targetObject.setPropName(float)」和「targetObject.getPropName()」 如果您建構以下 ObjectAnimator
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
  • 視要加入動畫的屬性或物件而定,您可能需要在檢視畫面上呼叫 invalidate() 方法,強制使用 更新動畫值只要在 onAnimationUpdate() 回呼。舉例來說,為 Drawable 物件的色彩屬性加上動畫效果,只會更新 再次繪製該物件時的畫面。「檢視畫面」上所有的屬性 setter,例如 「setAlpha()」和「setTranslationX()」 正確撤銷 View,因此無須在呼叫這些例項時使 View 失效 方法。如要進一步瞭解事件監聽器,請參閱 動畫事件監聽器

使用 AnimatorSet 編排多個動畫

在許多情況下,您可能會想播放根據其他動畫何時開始或 完成。Android 系統可讓您將動畫組合成 AnimatorSet,以便指定是否要啟動動畫 依序或指定的延遲時間後你也可以為 AnimatorSet 物件建立巢狀結構。

下列程式碼片段會播放下列 Animator 將物件儲存於 Cloud Storage 中

  1. 播放《bounceAnim》。
  2. 播放squashAnim1squashAnim2stretchAnim1stretchAnim2
  3. 播放《bounceBackAnim》。
  4. 播放《fadeAnim》。

Kotlin

val bouncer = AnimatorSet().apply {
    play(bounceAnim).before(squashAnim1)
    play(squashAnim1).with(squashAnim2)
    play(squashAnim1).with(stretchAnim1)
    play(squashAnim1).with(stretchAnim2)
    play(bounceBackAnim).after(stretchAnim2)
}
val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
}
AnimatorSet().apply {
    play(bouncer).before(fadeAnim)
    start()
}

Java

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

動畫事件監聽器

您可以在動畫播放期間透過下述的事件監聽器監聽重要事件。

您可以擴充 AnimatorListenerAdapter 類別, 實作 Animator.AnimatorListener 介面 (如果沒有的話) 想實作 Animator.AnimatorListener 的所有方法 存取 APIAnimatorListenerAdapter 類別提供空白 可以選擇覆寫的方法實作。

舉例來說,下列程式碼片段會建立 AnimatorListenerAdapter 僅適用於onAnimationEnd() 回呼:

Kotlin

ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            balls.remove((animation as ObjectAnimator).target)
        }
    })
}

Java

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

為 ViewGroup 物件的版面配置變更加上動畫效果

屬性動畫系統提供為 ViewGroup 物件變更的動畫功能 並讓使用者輕鬆為 View 物件建立動畫

您可以利用 LayoutTransition 類別。ViewGroup 中的檢視畫面 將動畫加入或消失時 或者當您呼叫 View 的 setVisibility() 方法搭配 VISIBLEINVISIBLEGONE。ViewGroup 中的其他 View 也可以 並在您新增或移除檢視畫面時,自動將物件加入新位置。您可以定義 以下 LayoutTransition 物件中的動畫 呼叫 setAnimator() 然後使用其中一個參數傳入 Animator 物件 下列 LayoutTransition 常數:

  • APPEARING - 此標記指出在以下項目上執行的動畫 。
  • CHANGE_APPEARING - 此標記指出在以下項目上執行的動畫 而隨著容器中出現新項目而變更。
  • DISAPPEARING - 此標記指出在以下項目上執行的動畫 從容器中消失
  • CHANGE_DISAPPEARING - 此標記指出在下列項目上執行的動畫 而會隨著容器中的某個項目消失

您可以為這四種類型的事件定義自訂動畫,藉此自訂外觀 來設定版面配置轉場效果,或指示動畫系統使用預設動畫。

如要將 android:animateLayoutchanges 屬性設為 true, ViewGroup 可以執行以下動作:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

將此屬性設為 True 時,系統會自動為 ViewGroup 以及 ViewGroup 中的其他 View。

使用 StateListAnimator 為檢視畫面狀態變更加上動畫效果

StateListAnimator 類別可讓您定義 檢視畫面的狀態也會改變此物件的行為就像是 Animator 物件,只要指定特定值,就會呼叫該動畫 (例如「已按下」或「聚焦」) 變更。

可在具有根層級的 XML 資源中定義 StateListAnimator <selector> 元素和每個子元素都指定的子項 <item> 元素 StateListAnimator 類別定義的另一個檢視畫面狀態。每項 <item> 包含屬性動畫集的定義。

例如,下列檔案會建立狀態清單動畫,可變更 x 和 y 縮放比例 寬度:

res/xml/animate_scale.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the pressed state; increase x and y size to 150% -->
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
        </set>
    </item>
    <!-- the default, non-pressed state; set x and y size to 100% -->
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>

如要將狀態清單動畫附加至檢視畫面,請新增 android:stateListAnimator 屬性如下:

<Button android:stateListAnimator="@xml/animate_scale"
        ... />

現在,當這個按鈕觸發時,系統會使用 animate_scale.xml 中定義的動畫 狀態變更。

此外,如要將狀態清單動畫指派給程式碼中的檢視畫面,請使用 AnimatorInflater.loadStateListAnimator() 方法,然後將動畫指派給 透過 View.setStateListAnimator() 方法調整檢視區塊。

或者,您可以在兩個區域之間播放可繪項目動畫,而非為檢視區塊的屬性建立動畫。 狀態變更來使用 AnimatedStateListDrawable。 當中一些系統小工具 Android 5.0 預設會使用這些動畫。以下範例說明 將 AnimatedStateListDrawable 定義為 XML 資源:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

使用 TypeEvaluator

如果您想為 Android 系統無法辨識的類型製作動畫,可以自行建立動畫 評估人員使用 TypeEvaluator 介面。 Android 系統已知有 intfloat 或顏色 IntEvaluatorFloatEvaluatorArgbEvaluator 類型支援 我們會以驗證人員為審查目標。

TypeEvaluator 中只有一個實作方法 介面為 evaluate() 方法這樣一來, 您所使用的動畫工具, 動畫的目前時間點FloatEvaluator 類別會示範 步驟如下:

Kotlin

private class FloatEvaluator : TypeEvaluator<Any> {

    override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any {
        return (startValue as Number).toFloat().let { startFloat ->
            startFloat + fraction * ((endValue as Number).toFloat() - startFloat)
        }
    }

}

Java

public class FloatEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

注意:執行 ValueAnimator (或 ObjectAnimator) 時,系統會計算 動畫 (介於 0 和 1 之間的值),然後計算該動畫的內插版本 你使用的內插器規格內插分數就是 TypeEvaluator 透過 fraction 參數接收的資料,因此您可以 計算動畫值時也不必考量內插器。

使用內插器

內插器會定義動畫中特定值如何計算為 讓應用程式從可以最快做出回應的位置 回應使用者要求舉例來說,您可以指定在整個動畫中線性播放動畫 也就是讓動畫在整個播放期間平均移動 非線性時間,例如在開頭或結尾使用加速度加速或減速功能

動畫系統中的內插器會收到 Animator 的分數, 動畫的經過時間。內插器會修改這個分數,以符合 生成動畫Android 系統提供了一組常見的內插器 android.view.animation package。如果這些都不適合您的 您可以實作 TimeInterpolator 介面並建立

舉例來說,以下比較預設內插器 AccelerateDecelerateInterpolatorLinearInterpolator 計算內插分數的方式。 LinearInterpolator 對經過的分數沒有影響。AccelerateDecelerateInterpolator 會加速顯示動畫, 減緩它的播放速度下列方法可定義這些內插器的邏輯:

加速分解內插器

Kotlin

override fun getInterpolation(input: Float): Float =
        (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f

Java

@Override
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

LinearInterpolator

Kotlin

override fun getInterpolation(input: Float): Float = input

Java

@Override
public float getInterpolation(float input) {
    return input;
}

下表顯示各指標所計算出的近似值 持續時間為 1000 毫秒的動畫內插器:

歷時毫秒 經過時間分數/內插分數 (線性) 內插比例 (加速/減速)
0 0 0
200 20% 0.1
400 40% 0.345
600 0.6 0.8
800 0.8 0.9
1000 1 1

如表格顯示,LinearInterpolator 會變更值。 相同速度,每 200 毫秒傳送 0.2 次AccelerateDecelerateInterpolator 會在 200 毫秒至 600 毫秒之間,變更超過 LinearInterpolator 的值,在 600 毫秒和 600 毫秒之間變化 1000 毫秒。

指定主要畫面格

Keyframe 物件包含可讓您定義 特定狀態在動畫特定時間點的成效每個主要畫面格也可以有 內插器,控制動畫在前一個兩個間隔間的行為行為 這個主要畫面格的時間和時間。

如要將 Keyframe 物件例項化,必須使用其中一個工廠函式 方法、ofInt()ofFloat()ofObject(),以取得適當的 Keyframe 類型。接著,您撥打 將 ofKeyframe() 工廠方法 取得 PropertyValuesHolder 物件。取得物件後 取得動畫效果器,方法是傳入 PropertyValuesHolder 物件,並 要建立動畫的物件下列程式碼片段說明如何執行這項作業:

Kotlin

val kf0 = Keyframe.ofFloat(0f, 0f)
val kf1 = Keyframe.ofFloat(.5f, 360f)
val kf2 = Keyframe.ofFloat(1f, 0f)
val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2)
ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply {
    duration = 5000
}

Java

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);

以動畫呈現檢視畫面

屬性動畫系統允許使用 View 物件與優惠的簡化動畫 以下是觀看動畫系統的一些優點。檢視畫面 動畫系統藉由變更繪製方式來轉換 View 物件。這是 會在每個 View 的容器中處理,因為 View 本身並沒有可操作的屬性。 這使得 View 變成動畫,但卻不會導致 View 物件本身發生變更。這個 導致運作異常的行為,例如物件仍儲存於原始位置 並在畫面上不同的位置繪製在 Android 3.0 中,新屬性和對應的 新增了 getter 和 setter 方法,藉此消除這個缺點。

屬性動畫系統 變更 View 物件中的實際屬性,即可為畫面上的 View 加入動畫。於 此外,View 也會自動呼叫 invalidate() 方法重新整理畫面。View 類別中用於顯示屬性動畫的新屬性:

  • translationXtranslationY:這些屬性可控制 檢視畫面以從左側和頂部座標設定的差異,由版面配置設定 都會在 Docker 容器中執行
  • rotationrotationXrotationY:這些屬性 控制樞紐點的 2D (rotation 屬性) 和 3D 的旋轉角度。
  • scaleXscaleY:這些屬性可控制 2D 縮放的 2D 縮放比例 以其樞紐點周圍檢視。
  • pivotXpivotY:這些屬性可控制 旋轉和縮放轉換的中心點根據預設 點位於物件的中心。
  • xy:這些簡單的公用程式屬性可用來描述 其容器中檢視畫面的最終位置, 列出左側和上方值的總和 TranslationX 和 translationY 值。
  • alpha:代表 View 的 Alpha 透明度。這個值為 1 (不透明) 預設值為 0,代表完全透明 (不會顯示)。

如要為 View 物件的屬性 (例如顏色或旋轉值) 建立動畫效果,您只需要 是建立屬性動畫工具 並指定想查看的資料檢視屬性 動畫。例如:

Kotlin

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)

Java

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

如需更多有關製作動畫的詳情,請參閱 動畫 ValueAnimatorObjectAnimator

使用 ViewPropertyAnimator 建立動畫

ViewPropertyAnimator 提供簡單的方法,可將多個動畫製作成動畫 View 的屬性並行,使用單一基礎 Animator 物件。運作方式與 ObjectAnimator 類似,因為其會修改 實際值,不過在以動畫形式呈現許多屬性時,更有效率 一次。此外,使用 ViewPropertyAnimator 的程式碼也很大 更簡潔易讀下列程式碼片段顯示使用多個 ObjectAnimator 物件,單一 ObjectAnimator,而ViewPropertyAnimator 同時為檢視畫面的 xy 屬性建立動畫效果。

多個物件動畫工具物件

Kotlin

val animX = ObjectAnimator.ofFloat(myView, "x", 50f)
val animY = ObjectAnimator.ofFloat(myView, "y", 100f)
AnimatorSet().apply {
    playTogether(animX, animY)
    start()
}

Java

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

單一物件動畫工具

Kotlin

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

Java

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

ViewPropertyAnimator

Kotlin

myView.animate().x(50f).y(100f)

Java

myView.animate().x(50f).y(100f);

如要進一步瞭解 ViewPropertyAnimator,請參閱對應的 Android 開發人員 網誌 貼文

在 XML 中宣告動畫

屬性動畫系統可讓您以 XML 宣告屬性動畫,而不必執行 更新執行個體在 XML 中定義動畫,可輕鬆重複使用動畫 以更輕鬆的方式編輯動畫序列

針對使用新屬性動畫 API 的動畫檔案,以及使用 舊版檢視動畫架構, 從 Android 3.1 開始,您應在 res/animator/ 目錄中儲存屬性動畫的 XML 檔案。

下列屬性動畫類別支援 XML 宣告 下列 XML 標記:

如要查看可在 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>

如要執行此動畫,您必須將程式碼中的 XML 資源加載至 AnimatorSet 物件,然後設定所有動畫的目標物件 再開始播放動畫。為方便起見,呼叫 setTarget() 會設定一個用於 AnimatorSet 所有子項的目標物件。以下程式碼說明如何執行這項操作:

Kotlin

(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply {
    setTarget(myObject)
    start()
}

Java

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

您也可以在 XML 中宣告 ValueAnimator,如下所示: 如以下範例所示:

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0f"
    android:valueTo="-100f" />

如要在程式碼中使用先前的 ValueAnimator,您必須 必須加載物件、 AnimatorUpdateListener, 取得更新後的動畫值,並用於其中一個檢視畫面的屬性 如以下程式碼所示:

Kotlin

(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply {
    addUpdateListener { updatedAnimation ->
        textView.translationX = updatedAnimation.animatedValue as Float
    }

    start()
}

Java

ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
        R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

xmlAnimator.start();

如需瞭解定義屬性動畫的 XML 語法,請參閱動畫 資源

可能對 UI 效能造成的影響

更新 UI 的動畫器會讓中的每個影格發生額外轉譯工作 因此,我們使用會耗用大量資源的動畫 可能會對應用程式效能造成負面影響

為 UI 加上動畫效果的工作會新增到以下項目的動畫階段: 算繪程序您可以查看動畫是否會影響 啟用剖析 GPU 轉譯功能,並 可以監控動畫階段詳情請參閱「 剖析 GPU 轉譯 逐步操作說明