[譯]Android 動畫的靈魂—— Interpolator

weixin_34290000發表於2016-10-31

用定製的非線性定時曲線改善你的動畫

在現實世界中的運動是非線性的。(當你穿過街道時,你只要略微將你盯著手機的眼睛瞄一眼街道就足夠保證你不會被車撞到。)當我們走路的時候,我們在加速。當我們停止的時候,我們慢慢減速到 0(除非我們被車撞了,這樣我們會體驗到我們朝著另一個方向突然加速)。當我們下落的時候,重力使我們加速下落,當我們跳起的時候,它又會降低我們的上升速度。無論如何,我們無法在整個運動中保持一個恆定的移動速度。

所以作為人類,當我們看到螢幕上的運動時(我們正在觀看手機上的動畫,並沒有留意到那些正在靠近我們的車輛的時候。),我們期望它也是同樣的非線性,因為這樣會讓人感覺更自然。通常來說,我們在應用裡嘗試實現的自然互動,它是用來幫助使用者更好的理解這些應用裡的虛擬世界究竟在發生什麼。不要嘗試用你奇特的動畫技巧讓他們驚奇;給他們感受起來很自然的動畫,以便於他們可以更容易的使用你的應用然後完成他們需要做的事情。

Android Interpolation

從一開始, Android 就已經提供了通過它的 Interpolator 實現來製作非線性動畫物件的能力。事實上,預設的動畫通常是加速進入和減速退出運動中的一個。更加重要的是,Android 也為開發者提供了改變預設運動的能力,以此來提供其他型別的速度變化。舉個例子,你可以使你的動畫快速的開始然後減速退出。或者,慢慢的開始然後逐漸加速。自從 Lollipop 版本 (API 21)釋出了以後,Android 又提供了基於路徑的定時曲線來完成更加複雜和靈活的控制。甚至於,如果你想要凸顯你的奇特,你可以使用線性 interpolation (但是請不要這樣做)。

有了這麼多的選項,那麼問題來了:你應該為你的動畫使用哪一個呢?

如此多的選擇!

在今年的 Google I/O 大會上,一個開發者靠近我問道:“我應該使用什麼型別的 interpolation 來讓一個 text 元素從邊上滑入?”

這是一個好問題,我建議更多的開發者應該為他們自己的應用問一下這個問題。

不幸的是,這個問題的答案是一個令人並不滿意的模糊答案,“看情況”。這取決於你,你的應用,這個動畫的上下文,你的使用者,以及許多其他的因素,沒人可以簡單的為你做決定。確實是有某種程度上較好與較壞方式的判定(例如:不要為移動的物體使用 LinearInterpolator ,讓你的動畫儘可能的快)。但是並沒有可以通用的“正確”答案。

我的推薦(確切答案的一個微不足道的替代品)是使用不同的 interpolators,然後在他具體的情況下試驗下,選擇感覺最好的那個。或者,更一般的說,寫一個簡單的測試應用,允許他使用不同 interpolator,然後簡單的比較下。

我意識到這是我們能為他(也是為每個人)提供的東西。這不是一個難寫的應用,但是用來比較內建的interpolator還是很有用的,對開發者來說它應該是很方便的,無論是使用或者是修改他們任意的定製需求。

所以下面的就是:

InterpolatorPlayground

703392-7c6d092b56fc93b3.png
InterpolatorPlayground 實戰

介紹下 InterpolatorPlayground,這是一個簡單的 Android 應用,你可以使用它來選擇幾個標準 interpolator 中的一個,然後實驗看看它們是如何影響一個動畫的。你可以改變動畫的持續時間以及 interpolator 的構造引數。通過給 UI 中各種物件新增 interpolation 動畫,你可以使 interpolation 曲線和產生的影響視覺化。最後,你可以為兩個 PathInterpolator 選項(平方和立方)拖動控制點來看看如何使用這個具體的類建立非常個性和靈活的定時曲線。

你也可以執行一些有趣的(儘管用處不大) interpolator,例如反彈和衝出(主要是因為他們在執行的時候看起來很有趣)。

一旦你決定為你的應用使用一個你喜歡的動畫,簡單的記下 UI 中的引數,然後在你的程式碼裡使用那些引數建立適當的 Interpolator。

它是怎樣執行的

你可以在你的程式碼裡插入一個 Interpolator 之後你就可以呼叫它。你可以不用理解其中的細節;你真正需要的是你正在尋找的運動效果。

但是如果你不關心它是如何執行的,那為什麼你還要選擇成為一名程式設計師呢?細節才是真正有趣的地方。

interpolator 執行的方式,或者更具體的說,interpolator 影響動畫定時曲線的方式,是通過改變當前完成時間的百分比來進行的。在 Android 中的每個動畫都設定了一個持續時間(預設的時長是 300 毫秒)。在動畫持續時間內的任意一個時間點,系統計算出已經執行了多長時間,然後呼叫 animation 讓它根據之前得到的時間來計算新的 animated 值。執行時間可以被表達成一個比例因子(0 是開始,1 是結束)。舉個例子,一個 animation 正進行到中間時刻,那麼它當前完成的比例因子就是 0.5,它的計算值就處於它的起始值和結束值的中間。

但是我們沒有直接傳遞那個比例因子,替代的我們通過一個 Interpolator 傳遞比例因子,這個 Interpolator 把當前完成的比例因子作為輸入然後返回另一個比例因子作為輸出。被插入的比例因子被我們傳遞給 animation 物件進行計算。

所以為了改變一個 animation 物件的定時曲線,我們只需要提供一個功能,它把一個當前已完成的比例因子轉換成另一個比例因子,然後使用這個新的比例因子來計算 animation 值。

舉個非常簡單的例子,假設我們建立了一個 Interpolator 通過返回比例因子的相反值來反轉 animation,它看起來是這樣的:

 public class ReverseInterpolator implements Interpolator {
    @Override 
    public float getInterpolation(float fraction) {
        return 1 - fraction;
    }
}

這個 interpolator 會使 animation 在開始的時候計算它的結束值(當輸入的比例因子為 0 的時候,被插入的比例因子則是 1 )然後在結束的時候計算開始值(當輸入比例因子為 1 的時候,被插入的比例因子則是 0 ).它會適當的改變那些位於結束值和起始值中間的比例因子。

Android 中內建的 Interpolator 類使用類似的功能,簡單的(例如 LinearInterpolator,它只是簡單的返回輸入值)和更加複雜的(例如 PathInterpolator,它使用平方、立方或者貝塞爾曲線決定返回值)都被用來計算比例因子,這樣使得豐富多彩的各種定時曲線都能符合大部分期望。如果你沒有找到你想要的,實現你自己的 Interpolator 也是很容易的。

在此同時,把視線從你的螢幕上移開。有輛車正在開過來。

相關文章