fb-script

2017年5月8日 星期一

簡化 UIView 動畫串接 (使用 Swift 3)

這篇算是悠閒時刻做的,不是教學,一整個是很放鬆的分享,那我們開始囉~
一般來說在使用 UIView.animate 要做動畫串接時,最無腦就這樣用

試想,啊如果要寫個 3 階段動畫,阿不就要接 3 層,那 3 層以上咧?哇賽那還真有點惡夢…..
當然在 open source 上已經有很多先驅寫了很多套件來處理這件事情,這篇就來嘗試自己手刻來解決。(感覺就是放假太無聊….)
好歐~先想想希望有個怎樣的套件來撰寫這類的程式,Hmmm…. 希望可以一直讓我加入動畫的設定,不用一直在那邊 UIView.animate(.....)
好歐那就有個 add 的方法,讓我可以這樣用

哇賽這樣看起來好直觀好爽啊,那就來試試看吧~
首先那個 animation 應該是某個容器吧,可以把每個動畫跟對應的設定參數放到類似佇列的結構中(這樣的用法執行起來是 FIFO),最後的 start() 就是啟動開始一個一個動畫跑吧!當然 start() 之後不能再接任何東西了….
好!那就動手做這個 animation 的類別吧~
這類別要有一個放動畫跟對應設定的陣列
陣列裡面放的就是動畫跟對應的參數設定,Hmmm….. 那就用一個內部類別來做這個結構吧!來看看 UIView.animate(.....) 這個方法到底有多少種參數宣告法!看了一下 extension 中的宣告,共有 4 種宣告的參數組合

可以看到總共有
  • duration: TimeInterval (必要)
  • animation: () -> Void(必要)
  • options: UIViewAnimationOptions(預設給 []
  • delay: TimeInterval
  • dampingRatio: CGFloat
  • velocity: CGFloat
  • completion: (Bool) -> Void
好吧!既然有這些那就把 completionoptions 做成 optional 然後 delaydampingRatiovelocity 就給預設值吧~所以這就是一個動畫的資訊類別。(optionsoptional是因為反正一定有給預設,在 class 裡面就不先給了)

好 der~ 那我們的佇列 class 目前就像這樣

好吧~有點想偷懶,那就把 add() 裡面的參數設計成大雜燴通通進來吧~而且 add() 之後還可以再次呼叫 add() 所以必須回傳自己,那 add() 就變這樣囉~

一些參數就直接給預設值,這樣在呼叫時想給就給,不想給就直接用預設值,連 duration 都給預設值 1,所以可以直接 add { // 動畫內容 } 這樣用,不想指定時間預設就是 1 秒。
好啦現在所有動畫的訊息都進入 animations 陣列中了,那在 start() 中就要一個一個的拿出來執行囉!所以 start() 就這樣設計吧~

OK~這樣就可以一直 add() 然後再最後來個 start() 就開始一個一個跑了。
但是這樣要怎麼具體使用呢?Hmmm….. 就掛在 UIView 之下吧!
來加個 Extension

這樣在任何 ViewController 中就可以像這樣使用

OK!! O…..K?????
感覺好像少了什麼!? 誒靠!我完全忘了 completion 的 callback …而且這樣用起來好像有點不足,我還想要能夠有暫停時間,就是兩個動畫中間停止個幾秒,所以最後用起來應該可以是這樣子才完整。

哇靠這樣看起來更爽更直觀~
整個執行起來就要是
1st (1 sec) -> 2nd (3 secs) -> 3rd (2 secs) -> print("pausing 3 secs") -> pause (3 secs) -> print("pause end") -> 4th (1 sec) -> print("ani end")
光想想這一堆串接要用原本的的寫法,真的會吐血啊~~~
實作細節都放在 Github 上了, 專案中還加了 Transition Queue 和 兩個混用的 Queue,要一點一點寫實在太多了, 原諒我偷懶的分享~

以上
GitHub: UIViewAnimationTransitionQueue

沒有留言:

張貼留言