建立自訂的轉場動畫

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

自訂轉場可讓您建立動畫,而內建轉場類別中沒有這類動畫。舉例來說,您可以定義自訂轉場效果,將文字和輸入欄位的前景顏色設為灰色,表示這些欄位在新畫面上已停用。這類變更可協助使用者查看您停用的欄位。

自訂轉場效果 (例如內建轉場效果類型) 會將動畫套用至開始和結束場景的子項檢視區塊。不過,與內建轉場效果類型不同,您必須提供擷取屬性值並產生動畫的程式碼。您也可以為動畫定義目標檢視區塊的子集。

本頁說明如何擷取屬性值及產生動畫,以建立自訂轉場效果。

擴充 Transition 類別

如要建立自訂轉場效果,請在專案中新增擴充 Transition 類別的類別,並覆寫下方程式碼片段中顯示的函式:

Kotlin

class CustomTransition : Transition() {

    override fun captureStartValues(transitionValues: TransitionValues) {}

    override fun captureEndValues(transitionValues: TransitionValues) {}

    override fun createAnimator(
        sceneRoot: ViewGroup,
        startValues: TransitionValues?,
        endValues: TransitionValues?
    ): Animator? {}

}

Java

public class CustomTransition extends Transition {

    @Override
    public void captureStartValues(TransitionValues values) {}

    @Override
    public void captureEndValues(TransitionValues values) {}

    @Override
    public Animator createAnimator(ViewGroup sceneRoot,
                                   TransitionValues startValues,
                                   TransitionValues endValues) {}
}

以下各節說明如何覆寫這些函式。

擷取檢視區塊屬性值

轉場動畫會使用「屬性動畫總覽」一文所述的屬性動畫系統。屬性動畫會在指定時間範圍內,將檢視區塊屬性從起始值變更為結束值,因此框架需要屬性的起始值和結束值,才能建構動畫。

不過,屬性動畫通常只需要檢視區塊所有屬性值的一小部分。舉例來說,顏色動畫需要顏色屬性值,而移動動畫則需要位置屬性值。由於動畫所需的屬性值是轉換專屬,因此轉換架構不會將每個屬性值提供給轉換。架構會改為叫用回呼函式,讓轉場效果只擷取所需屬性值,並儲存在架構中。

擷取起始值

如要將起始檢視區塊值傳遞至架構,請實作 captureStartValues(transitionValues) 函式。架構會針對起始場景中的每個檢視區塊呼叫這個函式。函式引數是 TransitionValues 物件,其中包含檢視區塊的參照和 Map 執行個體,您可以在其中儲存所需的檢視區塊值。在實作中,擷取這些屬性值,並將其儲存在對應中,傳回架構。

為確保屬性值的鍵不會與其他 TransitionValues 鍵衝突,請使用下列命名架構:

package_name:transition_name:property_name

下列程式碼片段顯示 captureStartValues() 函式的實作方式:

Kotlin

class CustomTransition : Transition() {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private val PROPNAME_BACKGROUND = "com.example.android.customtransition:CustomTransition:background"

    override fun captureStartValues(transitionValues: TransitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues)
    }

    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private fun captureValues(transitionValues: TransitionValues) {
        // Get a reference to the view
        val view = transitionValues.view
        // Store its background property in the values map
        transitionValues.values[PROPNAME_BACKGROUND] = view.background
    }

    ...

}

Java

public class CustomTransition extends Transition {

    // Define a key for storing a property value in
    // TransitionValues.values with the syntax
    // package_name:transition_class:property_name to avoid collisions
    private static final String PROPNAME_BACKGROUND =
            "com.example.android.customtransition:CustomTransition:background";

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        // Call the convenience method captureValues
        captureValues(transitionValues);
    }


    // For the view in transitionValues.view, get the values you
    // want and put them in transitionValues.values
    private void captureValues(TransitionValues transitionValues) {
        // Get a reference to the view
        View view = transitionValues.view;
        // Store its background property in the values map
        transitionValues.values.put(PROPNAME_BACKGROUND, view.getBackground());
    }
    ...
}

擷取結尾值

架構會針對結尾場景中的每個目標檢視區塊,呼叫一次 captureEndValues(TransitionValues) 函式。在其他方面,captureEndValues() 的運作方式與 captureStartValues() 相同。

下列程式碼片段顯示 captureEndValues() 函式的實作方式:

Kotlin

override fun captureEndValues(transitionValues: TransitionValues) {
    captureValues(transitionValues)
}

Java

@Override
public void captureEndValues(TransitionValues transitionValues) {
    captureValues(transitionValues);
}

在本例中,captureStartValues()captureEndValues() 函式都會叫用 captureValues() 來擷取及儲存值。captureValues() 擷取的檢視區塊屬性相同,但開始和結束場景中的值不同。架構會為檢視區塊的開始和結束狀態維護個別地圖。

建立自訂動畫師

如要對檢視畫面在起始場景中的狀態和結束場景中的狀態之間的變更進行動畫處理,請覆寫 createAnimator() 函式,提供動畫師。架構呼叫這個函式時,會傳入場景根檢視區塊和包含您擷取開始和結束值的 TransitionValues 物件。

架構呼叫 createAnimator() 函式的次數,取決於開始和結束場景之間發生的變更。

舉例來說,假設淡出或淡入動畫是透過自訂轉換實作。如果起始場景有五個目標,其中兩個從結束場景中移除,而結束場景有起始場景的三個目標加上一個新目標,則架構會呼叫 createAnimator() 六次。其中三項呼叫會為留在兩個場景物件中的目標製作淡出和淡入動畫。另外兩次呼叫會為從結尾場景移除的目標設定淡出動畫。其中一個呼叫會為結尾場景中的新目標加入淡入動畫效果。

如果目標檢視區塊同時存在於開始和結束場景中,架構會為 startValuesendValues 引數提供 TransitionValues 物件。如果目標檢視畫面只存在於開始或結束場景,架構會為對應引數提供 TransitionValues 物件,並為另一個引數提供 null

如要在建立自訂轉場效果時實作 createAnimator(ViewGroup, TransitionValues, TransitionValues) 函式,請使用您擷取的檢視區塊屬性值建立 Animator 物件,並將其傳回架構。如需實作範例,請參閱「 CustomTransition」範例中的 ChangeColor 類別。如要進一步瞭解屬性動畫師,請參閱「屬性動畫」。

套用自訂轉場效果

自訂轉場效果的運作方式與內建轉場效果相同。如要套用自訂轉場效果,請使用轉場效果管理工具,詳情請參閱「套用轉場效果」。