Android 中基於物理特性的動畫簡介

簡評:基於物理特性的動畫依賴於物理學定律,這能在動畫中表現出高度的現實感。

什麼是基於物理的動畫?

  • 這是一種遵循物理學定律的動畫形式
  • 能夠依據加速度和速度去計算和更新每一幀的動畫數值
  • 當受力平衡時,動畫為處於恆定運動或靜止狀態

和普通動畫有什麼不一樣?

  • 自然:動畫模仿實時的動作,看起來更自然
  • 反應:當目標值發生變化時,動畫保持動量(速度)並以更平滑的運動結束
  • 較少的視覺干擾:動畫看起來更流暢,反應靈敏度也更高

考慮在動畫期間目標值需要改變的情況。

左側使用 ObjectAnimator 構建的動畫以及右側基於物理 API 的動畫差異n

使用 Animator 構建的動畫是一種恆定速率的形式,並且具有固定的持續時間。為了適應目標值的變化,您需要在目標值更改時取消動畫,將當前值的動畫重新配置為新的起始值,並添加新的目標值。

在視覺上,這個過程中在動畫里創建了一個突然停止,並且之後又突然運動的一個不連貫的動作。

而使用基於物理的動畫 API 構建的動畫則自然得多。目標值的變化導致力的變化,新的運動適用於現有的速度,而且是連續過渡到新的目標,這樣的過程顯示的動畫效果更符合人們的日常認知。

添加基於物理的動畫支持庫

為了開始使用基於物理的動畫,將這個庫添加到 build.gradle 文件中:

compile "com.android.support:support-dynamic-animation:25.4.0"n

該庫提供了兩個 Animation 類:SpringAnimation 和 FlingAnimation

彈簧動畫(Spring Animation)

彈簧大家都知道,拉伸時會縮回去,壓縮時又會彈回來。

應用到 App 中就是這樣一個效果:

Spring translate animation applied on an ImageViewn

現在,讓我們先了解一下 Spring 的屬性,然後再看看如何實現:

彈力(Spring Force)

SpringForce 類允許開發者通過改變彈簧的阻尼比,剛度和靜止位置來控制彈簧的性能。一旦動畫開始,彈簧力就會更新動畫值和每幀的速度。動畫繼續,直到控制項受力平衡。

阻尼比(Damping ratio):受力平衡前的振蕩次數。您可以通過它來改變彈簧的彈性,阻尼比為零將無限振蕩,高阻尼比將很快停止動畫。

阻尼比可以從高彈性到無彈性常數。

DAMPING_RATIO_HIGH_BOUNCY = 0.2f; // more oscillationsnDAMPING_RATIO_NO_BOUNCY = 1f; // very few oscillationsn

剛度(Stiffness):振蕩速度。這將控制物體快速恢復到其靜止位置。

STIFFNESS_HIGH = 10_000f; // would quickly come back to its resting positionnSTIFFNESS_VERY_LOW = 50f; // would slowly come back, like a loose suspensionn

平衡位置(Resting position):彈力達到平衡的位置。

為了實現上面所示的動畫,我們創建一個 SpringAnimation 類的實例:

SpringAnimation springX = new SpringAnimation(mViewToBeAnimated,n new FloatPropertyCompat<View>("translationX") {nn @Overriden public float getValue(View view) {n return view.getTranslationX();n }nn @Overriden public void setValue(View view, float value) {n view.setTranslationX(value);n }n });nnSpringForce springForceX = new SpringForce(0f);nspringForceX.setStiffness(SpringForce.STIFFNESS_MEDIUM);nspringForceX.setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);nspringX.setSpring(springForceX);nspringX.start();n

對於構造函數 SpringAnimation,我們提供我們想要動畫化的視圖,以及我們想要動畫化的屬性。在這種情況下 imageView,我們想要動畫的對象是 TRANSLATION_X,我們想要動畫的屬性是左右顛倒視圖。

我們創建一個 springForce 實例,並將彈簧的最終靜止位置的值設置為零,以便視圖能回到起始點。

最後彈簧動畫效果就大功告成了!開不開心!

拋擲動畫(Fling Animation)

現在彈出一個控制項之後,讓我們看看如何做出像現實中物體上拋的效果。

上拋運動大家也都很熟悉,在現實世界中向上扔一個物體,它會有一個初速度,然後它在這個速度的慣性下繼續運動,直到引力的作用下逐漸停止。

為了模擬上拋運動向上階段的過程,我們將使用 FlingAnimation 庫中可用的類。

先看個例子,在橫軸和縱軸上移動一個物體,它的效果:

Fling translate animation applied on an ImageViewn

為了接收 callbacks,當動作開始時,我們需要設置一個姿勢監聽器。一旦檢測到這個回來的姿勢,我們會收到 onFling 回調,同時在坐標軸上有一個 downEvent,一個 upEvent 和一個速度(以每秒移動的單位像素為單位)。

設置 StartVelocity

默認情況下,起始速度設置為零像素 / 秒。在這種情況下,它會在下一幀中停止動畫。因此,您必須定義起始速度,以確保動畫不會馬上結束。

設置最小值和最大值

要在特定範圍內為屬性值設置動畫時,請設置最小和最大動畫值。一旦 Fling 動畫達到其最小 動畫值或最大動畫值,它將立即結束。

設置反作用力

需要設置反作用力來控制動畫變慢時的速度現在我們準備創建一個 Fling 動畫:

private GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {nn ...n @Overriden public boolean onFling(MotionEvent downEvent, MotionEvent moveEvent, float velocityX, float velocityY) {nn //Fling Right/Leftn FlingAnimation flingX = new FlingAnimation(mViewTobeFlung, DynamicAnimation.TRANSLATION_X);n flingX.setStartVelocity(velocityX)n .setMinValue(MIN_TRANSLATION) // minimum translationX propertyn .setMaxValue(maxTranslationX) // maximum translationX propertyn .setFriction(FRICTION)n .start();nn return true;n }n}n

對於 FlingAnimation 構造函數,我們提供我們想要的動畫對象和要動畫化的屬性。在這種情況下 imageView,我們想要動畫的對象是 TRANSLATION_X,最後,在 onFling() 方法中啟動 fling 動畫。

結論

使用新的基於物理的動畫系統,我們不需要為創建基於物理的動畫提供持續時間或開始和結束值。Google 已經開放介面讓開發人員能輕鬆創建酷炫動畫,只需幾行代碼即可模擬物理定律。

原文鏈接:Introduction to Physics-based animations in Android

推薦閱讀:手把手教你實現一個低配版象棋 AlphaGo

推薦閱讀:

大波新款 Emoji 表情正在前往你手機的路上
iOS系統和安卓系統哪個更安全?
你需要的不僅僅是一個答案
要被玩壞了?來看看那些手機大廠的「定製」姿勢

TAG:Android | 动画 | 编程 |