前提
視覺和產品現狀決定不能重新定義TabBar,只能在系統的TabBar上用lottie庫做動畫。
玩過lottie 的同學應該都知道,lottile 主流做法就是LOTAnimationView 加載bundle里面的.json資源文件。
由于iOS系統的TabBar繼承于UIView,它的子視圖即我們點擊的tabbar按鈕:UITabBarButton(此類只能在debug的時候看到,系統沒有暴露出來,所以我們沒辦法引用),但是我們在debug過程中發現它是繼承與UIControl。所以可以用虛函數方式來引用它:即UIControll *control =?UITabBarButton。這樣的目的是為了在它上面添加我們自定義的LotAnimationView
圖一
初始化CUstomLoATView ,繼承于LOTAnimationView,為什么這樣做下面會分析。
圖二
遍歷出tabbar 的子視圖UITabBarButton ,然后把CustomLotAVView 加到?UITabBarButton上去。self.imageViewMap 是存儲的初始化好的CustomLotAVView映射。具體結構@{@"1000": @"LotiView1",@"1001":@"lotiView2",@"1002",@"lotview3"}
圖三
然后根據tag值來取對應的lotiView
圖三就是打印出 UITabBarButton具體屬性參數,系統沒暴露出來,所以無法引用。
其他看注釋即可明白,
這里需要說明一下實現大致邏輯:
UITabbarItem 里面有一個tag,可以用來標示是那個這個item,初始化的時候我把item的tag 設置成上面self.imageViewMap的key值即tag。這樣做的目的是為了后面點擊tabbar的時候通過代理回調拿到item然后根據item的tag 取self.imageViewMap里面對應的lotiview。
總結一下:即建立起UITabbarItem 和lotiView 之間對應關系。然后在- (void)tabBar:(UITabBar*)tabBardidSelectItem:(UITabBarItem*)item 取對應的lotiView去做動畫,如果還沒看明白就看下面圖
在點擊tabbar 的回調里面拿到item.tag 再取到對應的lotiView,在調用[view play]即可做動畫!,標紅的是坑,下面會具體解釋
圖四:
踩坑一:
開始以為這樣做了之后就基本沒問題了,運行程序之后發現點擊tabbar沒反應。經過一系列判斷推測等等騷操作 的出結論LotiView 把事件攔截了導致事件沒有傳遞給其父視圖UITabBarButton,所以自定義一個CustomLoTAView 然后再里面的hittest強行把事件傳遞給其父視圖。具體請看代碼片段:
圖五
通過super 方法拿到View,其實就是CustomLoTAView 的實例。然后利用相應鏈 nextReponder來獲取其下層的事件接受著:即 父視圖-> UITbarBarButton。當然這代碼寫的不嚴謹,沒對nextResponder進行類型判斷。后面會加上去,但是對于目前的業務是足夠了
這樣就把點擊事件交給系統去處理。我們不用關心。
圖六
踩坑二:
現在來填圖四的坑,把圖四拿過來
會發現點擊tabbar的時候通過代理拿到item,然后通過item.tag 拿不到對應的CustomLoAView,真是日了狗了。又廢了一系列腦細包發現原因是:初始化的時候沒有給UIBarItem 的title和image。所以系統自動幫我們生產item。所以我們自己的tag 自然就沒有了,具體解決,看截圖:
YSDockItem 是一個對象 就是對UIBarItem 的一些titile,image 和tag 等一些參數,然后賦值:由于公司代碼不方便上傳具體結構,請見諒。
其中image 和title其實都是沒數據,所以self.tabBarItem 雖然初始化出來但是點擊- (void)tabBar:(UITabBar*)tabBardidSelectItem:(UITabBarItem*)item 時候這個item 是系統新生成的不帶初始化的tag,各位看官可以去試試。
所以生成一個空的image來占位。不讓系統在生成新的UITabBarItem。
由于真機效果視頻還在審核,先放一下gif的最后的效果:
具體代碼由于特殊規定不能全部上傳,請見諒!!