前言:很多動效都是多種動畫的組合,有時候你可能只是需要其中某個動畫,但面對龐雜的代碼庫或是教程,你可能比較困惑,本系列將復(fù)雜動效中不常見的動畫效果拆解出來便于學(xué)習(xí),授人以魚不如授人以漁。

對 TabBar 上的 TabBarItem 做漸變動畫是個很常見的需求吧,應(yīng)用了這個效果的應(yīng)用里以微信最為知名,首要問題是如何讓 TabBarItem 產(chǎn)生漸變效果。我在寫 iOS 視圖控制器轉(zhuǎn)場詳解這篇文章為 UITabBarController 寫轉(zhuǎn)場動畫 Demo 時嘗試添加這個漸變效果。你如果了解下 TabBarItem 會發(fā)現(xiàn)這個類并沒有公開的視圖屬性接口以便你添加動畫,以前我也搜索過在 TabBarItem 上添加動畫,沒有比較好的方案??戳死准冧h開源的 WXTabBarController 后發(fā)現(xiàn),如果你不了解 TabBarItem 的內(nèi)部結(jié)構(gòu)的話,這個問題你幾乎沒有辦法。得承認,我以前還從來沒有這么干過,打開了一片新天地。WXTabBarController 里似乎用 Reveal 來查看內(nèi)部視圖結(jié)構(gòu)的,不過我沒買這個軟件,后來想起了 Xcode 自帶的 View Debugging 功能,同樣能辦到這點,快速入門教程:raywenderlich 家出品的 View Debugging in Xcode 6。
于是,解決方案出來了,圖勝千言:


既然掌握了內(nèi)部視圖結(jié)構(gòu),那么傳統(tǒng)的 UIView 動畫就有用武之地了,想怎么玩都行,終于知道 Github 上那些 自定義 TabBar 的動畫怎么來的了。
在傳統(tǒng)的 View Controller Transition(也就是所謂的轉(zhuǎn)場)中實現(xiàn)這個效果會有一個小問題,那就是 TabBarItem。WXTabBarController 重寫了相關(guān)的屬性方法,切斷了 UITabBarController 對 TabBar 的控制,而在 UITabBarController 里,tabBar這個屬性是只讀的,對 TabBarItem 的公開接口基本不能修改,這就造成了后景偽裝圖標(biāo)的差異。
我實現(xiàn)的 SEGradualTabBarController,處理如下:

被選中的 TabBarItem 與其他 TabBarItem 的處理是相反的,切換后,切換后的 TabBarItem 也要進行反向處理,注意下就好了。SEGradualTabBarController 與 WXTabBarController 在 TabBar 的處理上大同小異,剩下的不同就在于前者使用轉(zhuǎn)場,后者使用 UIScrollView,這帶來了很多優(yōu)勢。
在滑動時根據(jù)滑動的距離來更新前后景圖標(biāo)的 alpha 值這很好理解,松手后呢?WXTabBarController 直接在 UIScrollView 的代理方法里實時更新 alpha 值:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
松手后該方法也會繼續(xù)調(diào)用直至滑動停止,實際上 WXTabBarController 的代碼里并沒有 UIView 動畫代碼。
SEGradualTabBarController 滑動時在手勢綁定的方法里實時更新 alpha 值,松手后的處理......我原本是打算用CADisplayLink,在實現(xiàn)自定義容器控制器轉(zhuǎn)場時就是采用的這個,后來發(fā)現(xiàn),都已經(jīng)有了內(nèi)部視圖了,直接使用 UIView 動畫不就得了。在交互轉(zhuǎn)場里,根據(jù)松手時的閾值判斷,可以選擇完成或是取消轉(zhuǎn)場,其中的動畫也會同步,不過在這里行不通,看第一張圖,在子 VC 間切換時, ViewController Transition 中涉及的子視圖都是 UITransitionView 的子視圖,而 TabBar 并不是 UITransitionView 的子視圖,也就無法享受 ViewController Transition 的福利了。
總體來說,在 View Controller Transition 中實現(xiàn) TabBar 的漸變效果比起 WXTabBarController 來得麻煩,后者還有個優(yōu)勢是兼容的版本更低,SEGradualTabBarController 最低只能是 iOS 7 了,不過馬上 iOS 10 都要來了。