由於使用者在背景中進行互動或處理作業,經常需要重新調整畫面上的物件位置。比起立即更新物件的位置,導致物件從一個區域閃爍,而是改為使用動畫,從起始位置移至結束位置。
Android 可讓您使用 ObjectAnimator
重新調整畫面上檢視物件的位置。請提供您想要物件固定的結束位置,以及動畫的時間長度。您也可以使用時間內插器來控制動畫的加速或減速。
使用 ObjectAnimator 變更檢視畫面位置
ObjectAnimator
API 可讓您以指定時間長度變更檢視畫面的屬性。其中包含的靜態方法,可根據您要建立動畫的屬性類型來建立 ObjectAnimator
執行個體。當您在畫面上重新調整檢視畫面的位置時,請使用 translationX
和 translationY
屬性。
以下範例 ObjectAnimator
會在 2 秒內,將檢視畫面從螢幕左側移至 100 像素的位置:
Kotlin
ObjectAnimator.ofFloat(view, "translationX", 100f).apply { duration = 2000 start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setDuration(2000); animation.start();
本範例使用 ObjectAnimator.ofFloat()
方法,因為平移值必須為浮點值。第一個參數是您要建立動畫的檢視畫面。第二個參數是您要建立動畫的屬性。由於檢視區塊必須水平移動,系統會使用 translationX
屬性。最後一個參數是動畫的結束值。在本例中,值為 100 表示距離畫面左側有許多像素的位置。
下一個方法可指定動畫播放的時間長度 (以毫秒為單位)。在此範例中,動畫會執行 2 秒 (2000 毫秒)。
最後一個方法會使動畫執行,進而更新檢視畫面在畫面上的位置。
如要進一步瞭解如何使用 ObjectAnimator
,請參閱「使用 ObjectAnimator 建立動畫」。
新增曲線動態效果
使用 ObjectAnimator
很方便,但根據預設,這會將檢視畫面重新調整到起點和終點之間的直線位置。質感設計仰賴曲線在螢幕上物件的空間移動,以及動畫的拍攝時間。使用曲線動態效果可讓應用程式產生更質感,同時讓動畫更有趣。
定義自己的路徑
ObjectAnimator
類別包含多種建構函式,可讓您搭配路徑使用兩個以上的屬性,一次為座標建立動畫效果。舉例來說,下列動畫工具使用 Path
物件為檢視畫面的 X 和 Y 屬性建立動畫效果:
Kotlin
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true) } val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply { duration = 2000 start() } } else { // Create animator without using curved path }
Java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true); ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path); animator.setDuration(2000); animator.start(); } else { // Create animator without using curved path }
弧形動畫的外觀如下:
圖 1 曲線路徑動畫。
Interpolator
是加/減速曲線的實作方式。如要進一步瞭解加/減速曲線的概念,請參閱 Material Design 說明文件。Interpolator
定義動畫中特定值如何計算時間函式。系統會為 Material Design 規格的三個基本曲線提供 XML 資源:
@interpolator/fast_out_linear_in.xml
@interpolator/fast_out_slow_in.xml
@interpolator/linear_out_slow_in.xml
使用 PathInterpoator
PathInterpolator
類別是 Android 5.0 (API 21) 中引入的內插器。它是以貝茲曲線或 Path
物件為基礎。加/減速的 Material Design 說明文件中的 Android 範例使用 PathInterpolator
。
PathInterpolator
具有以不同 Bézier 曲線類型為基礎的建構函式。所有 Bézier 曲線的開始與結束時間皆分別固定在 (0,0)
和 (1,1)
中。其他建構函式引數取決於建立的 Bézier 曲線類型。
舉例來說,如果是二次圓弧形曲線,則只需要一個控制點的 X 和 Y 座標:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.67f, 0.33f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.67f, 0.33f); } else { myInterpolator = new LinearInterpolator(); }
這會產生開始快速開始的加/減速曲線,並在接近結尾時減速。
Bézier 建構函式也同樣有固定的開始和結束時間點,但需要兩個控制點:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f); } else { myInterpolator = new LinearInterpolator(); }
如要進一步控制,可以使用任意 Path
來定義曲線:
Kotlin
val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val path = Path().apply { moveTo(0.0f, 0.0f) cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f) } PathInterpolator(path) } else { LinearInterpolator() }
Java
Interpolator myInterpolator = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Path path = new Path(); path.moveTo(0.0f, 0.0f); path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f); myInterpolator = new PathInterpolator(path); } else { myInterpolator = new LinearInterpolator(); }
這會產生與 cubic Bézier 範例相同的加/減速曲線,但改用 Path
。
您也可以將路徑內插器定義為 XML 資源:
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:controlX1="0.5"
android:controlY1="0.7"
android:controlX2="0.1f"
android:controlY2="1.0f"/>
建立 PathInterpolator
物件後,即可將其傳送至 Animator.setInterpolator()
方法。Animator
會使用內插器來判斷開始的時間或路徑曲線。
Kotlin
val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply { interpolator = myInterpolator start() }
Java
ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f); animation.setInterpolator(myInterpolator); animation.start();