使用彈簧物理特性以動畫呈現動作

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

物理導向 動作是由力驅動彈簧力量是 互動性和動作彈簧的特性如下: 防潮和硬度在彈跳動畫中,值和 速率是根據各 相框。

如果您希望應用程式動畫只朝某個方向變慢, 考慮使用阻礙 快速滑過動畫

彈簧動畫的生命週期

在彈簧效果的動畫中,SpringForce 類別可讓您自訂彈簧的硬度、阻尼比和 最終排序動畫開始時,彈簧效果就會立即更新 分別是動畫值和每個影格的速率動畫會繼續播放 直到彈簧力量達到平衡

舉例來說,如果您將應用程式圖示拖曳至畫面周圍,並在之後放開手指 只要將手指從圖示上提起,圖示就會平放回原始圖示 隱形,卻是熟悉的力量

圖 1 說明瞭類似的彈簧效果。加號 (+) 表示 圓圈中間表示透過觸控手勢施加的力。

春季版本
圖 1. 彈簧放開效果

建立彈簧效果

為應用程式建構彈簧效果的一般步驟如下: 如下所示:

下列各節討論建造春天的一般步驟 動畫。

新增支援資料庫

如要使用以物理為基礎的支援資料庫,您必須在專案中新增支援資料庫 如下所示:

  1. 開啟應用程式模組的 build.gradle 檔案。
  2. 將支援資料庫新增至 dependencies 區段。

    Groovy

            dependencies {
                def dynamicanimation_version = '1.0.0'
                implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version"
            }
            

    Kotlin

            dependencies {
                val dynamicanimation_version = "1.0.0"
                implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version")
            }
            

    如要查看這個程式庫目前的版本,請參閱 版本頁面上的動態動畫。

建立彈簧效果

SpringAnimation 類別可讓您建立 物件的彈簧效果如要建立彈簧效果,您需要 建立 SpringAnimation 執行個體 然後提供物件、要加上動畫效果的物件屬性,以及 (選用) 決定動畫閒置的最終彈簧效果。

注意:建立彈簧效果時,最終 您可以視需要選擇彈簧的位置。不過,您「必須」 再開始播放動畫

Kotlin

val springAnim = findViewById<View>(R.id.imageView).let { img ->
    // Setting up a spring animation to animate the view’s translationY property with the final
    // spring position at 0.
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f)
}

Java

final View img = findViewById(R.id.imageView);
// Setting up a spring animation to animate the view’s translationY property with the final
// spring position at 0.
final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);

彈跳動畫可以調整 實際屬性。下列為可用的資料檢視: 系統:

  • ALPHA: 代表檢視畫面上的 Alpha 透明度。值為 1 (不透明), 預設值為 0,代表完全透明 (不會顯示)。
  • TRANSLATION_X, TRANSLATION_YTRANSLATION_Z:這些 屬性控制檢視畫面的位置,以從其左側進行差異值檢視。 座標、頂端座標和高度,由其版面配置設定 都會在 Docker 容器中執行
  • ROTATION, ROTATION_XROTATION_Y:這些 資源控制 2D 的旋轉功能 (rotation 資源),以及 沿著樞紐點的 3D 顯示。
  • SCROLL_X」和 SCROLL_Y:這些 屬性會指出來源左側和頂端邊緣的捲動偏移 單位。以及 已捲動。
  • SCALE_X」和 SCALE_Y:這些 屬性可控制資料透視點周圍檢視畫面的 2D 縮放比例。
  • X, YZ:這些是基本資料 公用程式屬性,用於說明檢視畫面的最終位置 都會在 Docker 容器中執行

註冊事件監聽器

DynamicAnimation 類別提供兩個 聽眾:OnAnimationUpdateListenerOnAnimationEndListener。 這些事件監聽器會監聽動畫的更新,例如當 變更動畫值及結束播放時

OnAnimationUpdateListener

如果您想為多個檢視畫面加上動畫效果,藉此建立鏈結動畫, 可以設定OnAnimationUpdateListener。 ,在目前的檢視畫面發生變更時,就接收回呼 資源。回呼會通知其他檢視畫面更新其彈簧位置 根據目前資料檢視資源中產生的變更。如要註冊 請依照下列步驟操作:

  1. 呼叫 addUpdateListener() 方法,並將事件監聽器附加到動畫。

    注意:您必須註冊更新 接聽程式。不過,更新事件監聽器應 只有在您需要對動畫值的每個影格更新時,才註冊 並輸入變更內容更新事件監聽器會阻止動畫 會在另一個執行緒上執行

  2. 覆寫 onAnimationUpdate() 方法,將目前物件中的變更通知呼叫端。 下列程式碼範例說明瞭 OnAnimationUpdateListener

Kotlin

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties
val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 ->
    SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to
            SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y)
}
val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 ->
    SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to
            SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y)
}

// Registering the update listener
anim1X.addUpdateListener { _, value, _ ->
    // Overriding the method to notify view2 about the change in the view1’s property.
    anim2X.animateToFinalPosition(value)
}

anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }

Java

// Creating two views to demonstrate the registration of the update listener.
final View view1 = findViewById(R.id.view1);
final View view2 = findViewById(R.id.view2);

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties
final SpringAnimation anim1X = new SpringAnimation(view1,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim1Y = new SpringAnimation(view1,
    DynamicAnimation.TRANSLATION_Y);
final SpringAnimation anim2X = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_X);
final SpringAnimation anim2Y = new SpringAnimation(view2,
        DynamicAnimation.TRANSLATION_Y);

// Registering the update listener
anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

// Overriding the method to notify view2 about the change in the view1’s property.
    @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2X.animateToFinalPosition(value);
    }
});

anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

  @Override
    public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,
                                  float velocity) {
        anim2Y.animateToFinalPosition(value);
    }
});

OnAnimationEndListener

OnAnimationEndListener 通知動畫結束。您可以設定要接收的事件監聽器 當動畫達到平衡或取消時回呼。目的地: 註冊接聽程式,請按照下列步驟操作:

  1. 呼叫 addEndListener() 方法,並將事件監聽器附加到動畫。
  2. 覆寫 onAnimationEnd() 方法,以便在動畫達到平衡時接收通知 或是已取消

移除事件監聽器

如要停止接收動畫更新回呼和動畫結束回呼, 打電話給removeUpdateListener()removeEndListener() 方法。

設定動畫起始值

如要設定動畫的起始值,請呼叫 setStartValue() 方法,並傳遞動畫的起始值。如果未設定 起始值,動畫會使用物件屬性目前的值 做為起始值

設定動畫值範圍

您可以設定動畫的最小值和最大值 將屬性值限制在特定範圍。此外也有助於控管 範圍以動畫呈現含有內建範圍的屬性 alpha (從 0 到 1)。

  • 如要設定最小值,請呼叫 setMinValue() 方法,並傳遞該屬性的最小值。
  • 如要設定最大值,請呼叫 setMaxValue() 方法,並傳遞該屬性的值。

這兩種方法都會傳回要設定該值的動畫。

注意:如果您已設定起始值,且 定義動畫值範圍,請確定起始值在 最小值和最大值範圍

設定起始速度

起始速率定義了動畫屬性變更 動畫開頭。預設起始速率設為 0 每秒像素數。您可以使用觸控速率設定速率 手勢或以固定值做為起始速度。如果您選擇 提供固定值 (建議以每秒 dp 為單位) 然後轉換成每秒像素以每秒 dp 來定義值 可讓速度不受密度和板型規格影響。如要 關於將值轉換為每秒像素數的資訊,請參閱 將每秒 dp 轉換為每秒像素 專區。

如要設定速率,請呼叫 setStartVelocity() 方法並傳送速率 (以每秒像素為單位)。此方法會傳回 設定速率的彈簧彈力物體

注意:請使用 GestureDetector.OnGestureListener 或 可擷取及計算的 VelocityTracker 類別方法 觸控手勢的速度

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        …
        // Compute velocity in the unit pixel/second
        vt.computeCurrentVelocity(1000)
        val velocity = vt.yVelocity
        setStartVelocity(velocity)
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
// Compute velocity in the unit pixel/second
vt.computeCurrentVelocity(1000);
float velocity = vt.getYVelocity();
anim.setStartVelocity(velocity);

將每秒 dp 轉換為每秒像素

彈簧速率須為每秒像素數。如果您選擇提供 固定值做為速率起點,請提供以每秒 dp 為單位的值 然後轉換成每秒像素如果是轉換,請使用 applyDimension() TypedValue類別中的方法。詳情請參閱 程式碼範例:

Kotlin

val pixelPerSecond: Float =
    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)

Java

float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());

設定彈簧屬性

SpringForce 類別會定義 getter 以及每個彈簧屬性的 setter 方法 長寬比和硬度如要設定彈簧屬性,請務必 擷取彈簧彈力 或是建立自訂彈簧 也可以設定屬性如要進一步瞭解如何建立自訂的 請參閱 建立自訂彈力 專區。

提示:使用 setter 方法時,您可以 建立方法鏈結,因為所有 setter 方法都會傳回彈簧 物件。

阻尼比

阻尼比代表彈簧振動逐漸減少的情況。變更者: 就能使用阻尼比量定義振幅衰減的速度 從一次彈跳轉至下一次你可以透過四種方式 春季:

  • 如果阻尼比大於 1,則會發生過度取樣。有了 則該物件會輕微回到其餘位置。
  • 阻尼比等於 1 時,會發生嚴重濕度。有了 物件會在最短的時間內傳回其他位置。
  • 當減壓率低於 1 時,會發生偏誤。有了 移動其餘位置,讓物件反覆出現 之後會逐漸接近剩餘位置
  • 阻尼比等於零時,則表示未取樣。這樣就能 物件可能會永久消失

如要將阻尼比和春季相加,請執行下列步驟:

  1. 呼叫 getSpring() 方法,擷取彈簧並增加阻尼比。
  2. 呼叫 setDampingRatio() 方法,並傳遞您要新增至 彈簧的取樣率。 方法會傳回設定阻尼比的彈簧力物件。

    注意:阻尼比必須為 非負數。如果您將阻尼比設為 0,春天就會 永遠不會達到剩餘的位置換句話說,它會不斷波動。

以下是系統提供的阻尼比常數:

圖 2:高彈力

圖 3:中型彈跳

圖 4:低彈力低

圖 5:無彈力

預設的取樣率設為 DAMPING_RATIO_MEDIUM_BOUNCY

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        …
        // Setting the damping ratio to create a low bouncing effect.
        spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY
        …
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
// Setting the damping ratio to create a low bouncing effect.
anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY);
…

硬度

Stiffness 會定義彈簧常數, 春季。硬幣會為連接的物體施加更多力 當春季不在休息位置時。 如要為春季增添硬度,請執行下列步驟:

  1. 呼叫 getSpring() 方法來擷取彈簧來新增硬度。
  2. 呼叫 setStiffness() 方法,並傳遞您要新增至 Spring 的 Stiffness 值。 方法會傳回要設定硬度的彈簧力物件。

    注意:硬性必須是 正數。

以下是系統提供的硬度常數:

圖 6:高硬度

圖 7:中等硬度

圖 8:低硬度

圖 9:非常低硬度

預設的硬度設為 STIFFNESS_MEDIUM

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        …
        // Setting the spring with a low stiffness.
        spring.stiffness = SpringForce.STIFFNESS_LOW
        …
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
// Setting the spring with a low stiffness.
anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW);
…

建立自訂彈力

除了使用預設值之外,您也可以建立自訂彈力 是不是非常喜歡有了自訂的彈簧效果 多個彈簧效果創作春季樂章後 就能設定阻尼比和硬度等屬性

  1. 建立 SpringForce 物件。

    SpringForce force = new SpringForce();

  2. 呼叫各自的方法來指派屬性。你也可以 方法是建立方法鏈

    force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);

  3. 呼叫 setSpring() 方法,將彈簧設為動畫。

    setSpring(force);

開始播放動畫

有兩種方法可以開始彈簧效果:呼叫 start() 或呼叫 animateToFinalPosition() 方法。這兩種方法需要在主執行緒上呼叫。

animateToFinalPosition() 方法會執行兩項工作:

  • 設定彈簧的最終位置。
  • 開始播放動畫 (如果尚未開始播放)。

由於這個方法會更新彈簧的最終位置,並啟動 必要時,您隨時能呼叫這個方法來更改 動畫。例如,在鏈結的彈簧效果中 取決於其他資料檢視以這類動畫來說 相當方便 animateToFinalPosition() 方法。在鏈結的彈簧效果中使用這個方法時,您就不必 您要更新的動畫是在執行中是否正常執行。

圖 10 說明瞭連鎖彈簧動畫,其中動畫 資料檢視需要其他資料檢視

春季示範鏈結
圖 10.春季示範

如何使用「animateToFinalPosition()」 方法後,請呼叫 animateToFinalPosition() 方法,然後傳遞彈簧的其餘位置。您也可以調整其他設定 方法是呼叫 setFinalPosition() 方法。

start() 方法會 不要立即將屬性值設為起始值。屬性 值會隨動畫脈衝而改變,也就是繪製過程之前發生。 因此,變更會反映在下一個頁框中,就像 這些值會立即設定

Kotlin

findViewById<View>(R.id.imageView).also { img ->
    SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply {
        …
        // Starting the animation
        start()
        …
    }
}

Java

final View img = findViewById(R.id.imageView);
final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y);
…
// Starting the animation
anim.start();
…

取消動畫

您可以取消或跳到動畫的結尾。理想情況 應用程式需要取消或跳至 API 階段的最終版本 互動要求立即終止動畫。這是 大多是因為使用者突然離開應用程式,或檢視畫面變成隱藏狀態。

有兩種方法可用來終止動畫。 cancel() 方法 終止動畫。 skipToEnd() 種方式 停止動畫到最終值並終止動畫。

終止動畫前,請務必先檢查 今年的春季如果狀態遭到破壞,動畫就永遠無法達到 剩下的部分 如要查看彈簧的狀態,請呼叫 canSkipToEnd() 方法。如果 彈簧會遭到阻斷,這個方法會傳回 true,否則 false

知道彈簧的狀態後,就能依下列方式終止動畫: 使用 skipToEnd() 方法或 cancel() 方法。 cancel() 種方式 「必須」只能在主執行緒上呼叫。

注意:一般來說, skipToEnd() 方法造成的 就讓整個畫面變得跳躍