由於使用者互動或幕後處理,螢幕上的物件經常需要重新定位。與其立即更新物件的位置,導致物件從一個區域閃爍,而是改用動畫,將物件從起始位置移至其結束位置。
Android 允許您在螢幕上重新調整檢視物件的位置,是使用 ObjectAnimator
。您可以提供物件要停留的終點位置,以及動畫的時間長度。您也可以使用時間插補器控制動畫的加速或減速。
使用 ObjectAnimator 變更檢視畫面位置
ObjectAnimator
API 提供一種方法,可變更指定時間長度的檢視畫面屬性。它包含靜態方法,可根據您要製作動畫的屬性類型建立 ObjectAnimator
例項。調整檢視畫面在螢幕上的位置時,請使用 translationX
和 translationY
屬性。
以下是 ObjectAnimator
的範例,這個 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
使用 PathInterpolator
PathInterpolator
類別是 Android 5.0 (API 21) 推出的插補器。它是以 Bézier 曲線或 Path
物件為基礎。Material Design 說明文件中的 Android 範例會使用 PathInterpolator
。
PathInterpolator
具有以不同類型貝茲曲線為基礎的建構函式。所有貝茲曲線的起點和終點分別固定為 (0,0)
和 (1,1)
。其他建構函式引數則取決於所建立的貝茲曲線類型。
舉例來說,對於二次貝茲曲線,只需要一個控制點的 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(); }
這會產生緩和曲線,一開始快速移動,然後在接近結尾時減速。
立方貝茲曲線建構函式同樣具有固定的起點和終點,但需要兩個控制點:
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(); }
這是 Material Design 強調減速的漸變曲線實作。
如要進一步控管,您可以使用任意 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(); }
這會產生與立方貝茲曲線範例相同的漸變曲線,但會改用 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();