前提
视觉和产品现状决定不能重新定义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的最后的效果:
具体代码由于特殊规定不能全部上传,请见谅!!