CYLTabBarController: 自定义一个简单的 tabbar
先说结论:
通过对一些第三方库一些调研, 在 github 之上 , 笔者没有找到特别高质量且低耦合的第三方 自定义 tabbar 库, 且通过查看第三方库的源码, 笔者发现了一些之前忽视的自定义 tabbar 的相关参数, 可以更加的去自定义一些UI
而且笔者通过调研一些app (比如微信), 发现这些 app 也在使用原生控件, 所以笔者认为原生控件可以满足大多数的 app 的需求, 所以笔者认为, 在不是必须的情况下, 没有必要一定全部重写 tabbar
那么问题来了, 我们如何很好的自定义原生 tabbar 呢?
目前可以自定义的UI
首先我们要清楚, 系统提供了哪些接口来自定义 tabbar, 我们能做什么
tabbar 高度
tabbar 默认/选中 图片
tabbar 默认/选中 文字以及文字属性
tabbar 默认/选中 文字以及文字属性
tabbar 整体的背景图片/颜色
tabbar 整体的阴影
tabbar 选中时候的背景图片(如果想要纯色, 请设置为纯色图片)
tabbarItem 的一些 button 的宽度
tabbar title/image 的偏移
我们不能做什么
tabbar 上 Button 上的 UI 以及相关动画/布局
tabbar 红点的样式, 但是 iOS 10 添加了一些相关的新接口
tabar 整体的背景
自定义样式的按钮/或者不规则的按钮
但是这上边的事情我们真的就不能解决了吗, 当然不是
对于背景, 虽然系统没有提供接口, 但是 UIView 上的问题往往通过下面三个步骤都能解决
1.遍历子视图
2.插入视图
3.调整视图层级
而红点样式, 同理 我们可以找到 对应的 Button 然后向上面添加 特殊 tag 的 view, 这样就可以自定义样式了, 起码微信就是这么做的.
至于自定义按钮的话, 我会在下面讲解 CYLTabBarController 的时候进行说明
CYLTabBarController
目前发现的 github 上标星最多的 自定义 tabbarViewController 第三方框架
这个库的主要作用是添加一个 PLUS 按键
实现类似如下的效果
优点:
实在 UITabViewController 与 UITabBar 的基础之上进行的再次封装, 低耦合,接入基本上没有什么特别大的成本
缺点:
1 它目前截获了 tabbarController 的 delegate, (可以进行优化)
2 它的 tabbarItem 使用的是 navgationController 的, 没有使用导航控制器的根控制器 (可以进行优化)
3 由于是在原生控件基础之上的封装, 所以对 UI 的可定制和原生相比提升不大
4 tabbarButton 的布局只能是均与分布, 在 iPad 上表现不佳(可以优化)
就我上面说的优缺点, 我来进行一下解释:
首先这个库的自定义按钮所对应的其实是一个操作,而不是对应到相应的控制器, 所以应用场景更适合类似中间提供 分享/发状态/拍照 等功能.
缺点中我在后面添加了很多(可以进行优化)的标识, 有兴趣的同学可以和我讨论一下或者自己去看一下如何优化.
CYLTabBarController 实现
TabbtController
使用自定义的 tabbar, 通过初始化方法 得到 viewControllers 与 configs, 然后逐条设置并且添加到 tabViewController
Tabbar
先注册一个 plus button, 然后遍历 tabbar 的所有子view, 然后把 button 重新布局,
plusbutton 一般高于 tabbar , 使用
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
来判断是否点击了 plus button
总结起来很简单, 就只在上边加一个按钮, 再把其他东西重新布局, 所以说及时看起来不是原生的, 其实我们动动脑子也是可以的
但是每个公司不一样, 交互一不一样, 原生的毕竟有各种限制
那么问题来了, 如果我就是要完全重写 Tabbar, 有哪些要注意的
如果完全重写 TabbarVC 的关键点
- 为了实现原生的效果 要监听 viewcontroller 的 tabarItem 的各种参数的变化
- 自定义的 tabbar 要自己定制布局规则 (iPad 的上尤为重要)
- 为了响应 hidesBottomBarWhenPushed, 需要与 navigationController 配合, 在执行动画的时候改变 Tabar 的层级, 实现类似原生的效果
- 如果想完全解耦, 还想迁移完全无成本,可能需要把接口定制为与原生控件相同, 需要研究原生的所有规则
当然, 我上边罗列的点,其实也有问题,就是我仍然想使用系统提供的参数接口, 比如是 controller 的一些类似 tabbarItem 的参数, 因为我个人是不希望因为某一个控件的自定义, 而造成其他所有代码都要为之而发生变化.
但是要说的是, 如果真的有需要, 怎么写都可以,实现了效果才是最重要的