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系統和安卓系統哪個更安全?
※你需要的不僅僅是一個答案
※要被玩壞了?來看看那些手機大廠的「定製」姿勢