Android屬性動畫:動畫流控制

zerob13發表於2014-07-29

今天的文章裡,我將會和大家討論對動畫流的控制。我們可以通過Animator系列的API來控制動畫的開始、停止和取消。在 KitKat也就是API level 19中,我們還可以控制動畫的暫停和恢復。在本文中,我將會帶你體驗整個動畫流的控制,並且通過一些函式方法來讓你能夠觀察到動畫的狀態。

動畫流介紹

在之前的教程中,我們已經使用過多次Animator.start這個方法。這個方法是用來讓動畫從第一幀開始播放。該方法只是動畫流控制方法集中的一個方法而已,完整的方法集合如下所示:

start這個方法顧名思義是用來讓動畫從開頭開始播放的。如果動畫設定了一個大於0的播放延遲(startDelay),那麼呼叫該方法後還需要等到延遲的時間過去才回開始播放。
我們有兩種停止動畫的方法,你可以用end方法抑或cancel方法來停止一個播放著的動畫。在兩種方式中動畫都會終止並且只有再次呼叫start方法才會重新開始播放。兩者的區別則在於停止後動畫所在的狀態,當你使用cancel方法來停止動畫後,動畫只是停止了它的時間軸,動畫的狀態會停在一箇中間態(intermediate state)。如果通過end 方法來停止一個動畫,那麼動畫會直接快進到該動畫最後一幀並且停止,所有的物件都會保持在動畫最終結束後的狀態。
在 Kitkat 中增加的沒有怎麼被大家關注到的新API則是帶來了動畫可以暫停和恢復的能力。在那之前,一個動畫如果被取消並且停留在當前的中間態,此時你用start方法去重啟動畫,動畫只會從一開始重新播放。現在,你則可以呼叫pause方法來暫停當前播放中的動畫,pause也會有和cancel方法一樣的功效讓動畫停留在中間態,但是當你使用resume 方法去恢復這個動畫的時候,動畫會從這個狀態繼續播放下去。
現在,讓我們來實踐下看看效果。我們新建一個 Activity 並且包含一個 私有的動畫物件。並且在 onCreate 回撥中初始化這個動畫。

我們的動畫是一個簡單的旋轉動畫,它將把一個圖片完整旋轉360度五次。被旋轉的圖片會在 layout 的 XML 檔案中定義好,並且給予一個叫some_image的id。這個layout同時也包含了五個按鈕分別是:Start、End、Cancel、Pause以及Resume。這五個按鈕分別代表了動畫的五個呼叫方法。

這些方法只是簡單的呼叫了相應的動畫控制呼叫。下面會有兩張gif圖片來演示效果。上邊的動畫展示了end方法和cancel方法的區別。可以注意到,cancel讓圖片保持在停止時的中間態,但是end則讓動畫到了最後的狀態。
下邊的動畫則演示了pause和resume方法。可以注意到,pause 和cancel都暫停了動畫的時間軸。但是現在我們可以用resume 呼叫去恢復動畫的時間軸了。

PropertyAnim_EndCancel

PropertyAnim_PauseRestart

動畫狀態的查詢

有些時候,我們需要去查詢當前動畫的狀態,這個需求可以通過下面這些方法來完成。

如果當前動畫已經呼叫了start函式並且還沒播放完成也沒有被取消掉,那麼isStarted方法會返回true。請注意,isStarted 方法最低的 API 需求是 14.同時,就算是在動畫播放延遲中,該方法依然會返回 true。這就是這個方法和 isRunning 方法的不同點,isRunning 方法只會在動畫確實在播放並且還沒停止的時候返回 true。

在 API 19 的時候,isPaused 方法被加入進來。這是由於那時候動畫可以被暫停和恢復了,如果 isPaused 返回了 true,那麼說明當前動畫是在暫停狀態下,反之亦然。

為了演示這些觀察方法的效果,我們會通過一個包含三個顯示動畫狀態文字框的例子來解釋。這三個文字框都會在Activity中做為TextView成員變數存在。

於此同時,我們在onCreate中新增下列三行程式碼來把這些文字框從layout中獲取到。

我們還建立了一個根據當前動畫狀態來更新這些文字框的方法。

我們在初始化以後每次修改動畫流的時候都去呼叫setStatusTexts方法,比如說,當我沒呼叫cancelAnimation的時候,程式碼是這樣的:

演示的結果我們可以從下面上方的動畫中看到。這裡我也建立了兩個動畫,一個演示End和cancel效果,另一個演示pause和 Resume效果。可以注意到,動畫的執行狀態在你點選了End和cancel之後是相同的,就算視覺上看兩者並不一樣。這說明了,你沒法通過動畫的狀態來區分出當前動畫是通過 End 呼叫還是cancel呼叫來停止的。這兩者情況下,isStarted和isRunning都會返回false。

PropertyAnim_EndCancelStatus

PropertyAnim_PauseResumeStatus

而下邊的動畫則顯示了pause和resume呼叫的效果。當我們通過pause呼叫去暫停動畫時,isPaused會返回true。然後通過 resume呼叫去恢復動畫播放後,isPaused也會變成false。可以注意到,圖中如果動畫是自然結束的,動畫的狀態並沒有改變。當然,動畫停止播放後,isStarted和isRunning肯定應該是返回false的。實際上,在動畫自然停止後,如果我們再去呼叫 isStarted和isRunning他們的的確確會返回false。而動畫中的例子我們並沒有在動畫自然停止後去更新狀態,所以我們並不知道當前的狀態,自然那幾個文字框也就沒有更新。為了能夠更新到最新的狀態,我們可以在動畫中新增AnimatorListener和 AnimatorPauseListener這兩個監聽,這兩個監聽具體的使用方法會是下一講的主要內容。

如果你對教程中的例子有興趣,歡迎去 GitHub 上下載完整程式碼。

相關文章