TabBarController
当你发现最新的 Zeplin 项目更新中设计师设计的 TabBar 高度不匹配 49px 时有多无聊?或者当你发现他们只制作了 TabBar 的先进设计,不能作为 UITabBar 的子类时?我们都知道那个时刻当你不得不想象一个自定义的层级结构来为设计师的 App ...
TabBarController 就像是一个 UITabBarController,允许你自定义 TabBar、转换和动画。你甚至可以为你的 TabBar 设置一个自定义锚点。你想要一个顶部的 TabBar 呢?还是只是在 tvOS 上的底部 TabBar?嗯……你只需使用 0 行代码就可以轻松完成所有这些,直接从你的 Storyboard 中(或者如果你不是 Storyboard 的大粉丝,你可以程序化地完成)
要求
Xcode 9.0 Swift 4.0
示例
要运行示例项目,克隆仓库,然后首先从 Example 目录中运行 pod install
。
安装
TabBarController 可以通过 CocoaPods 获取。安装它,只需在您的 Podfile 中添加以下行:
pod 'TabBarController'
使用说明
场景板
您可以直接从场景板设置TabBarController,要这么做
- 在场景板上添加一个UIViewController,并使其继承自TabBarController
- 更改TabBarController的场景板跃迁数量属性
- 添加继承自TabBarSegue的自定义跃迁
- 对于每个跃迁,您必须设置一个以'tab'开头并以它在TabBar中的索引结尾的标识符
例如:如果您想在标签页中有4个viewController,则必须将storyboardSeguesCount设置为4,并将自定义跃迁命名为tab0、tab1、tab2和tab3
好了!
程序化
let tabBarController = TabBarController(viewControllers: [...])
self.present(tabBarController, animated: true, completion: nil) // present it, set it as rootViewController, what ever..
隐藏标签栏
self.hidesBottomBarWhenPushed = true // automatically hide tabBar when pushed
self.tab.controller?.setTabBarHidden(true, animated: true) // manually hide tabBar, animated or not
查看iOS9ViewController.swift示例
滚动到顶部
如果您想在标签栏中选择标签时,处理像系统UITabBarController一样的滚动到顶部功能
func tabBarAction() {
//
self.tableView.setContentOffset(.zero, animated: true)
}
查看iOS9TableViewController.swift示例
标签
TabBarController为UIViewController提供扩展
self.tab.controller // return the tabBarController of self
self.tab.bar // return the tabBar of self.tab.controller
self.tab.barItem // return the tabBarItem of self's parent in TabBarController
self.tab.navigationController /* In case of the root view controller of your controller's tab is a UINavigationController, TabBarController add it in private parent controller.
Using self.tab.navigationController on this private parent controller (via self.tab.controller?.viewControllers for example) return your navigationController*/
self.tab.isNavigationController // return true if self.tab.navigationController != nil
NavigationController
TabBarController 允许您将 UINavigationController 作为 tabBarController 的每个 tab 的根视图控制器。但为了做到这一点,它会在一个私有父控制器中添加它,并将其代理设置为 TabBarController。如果您想为您的 UINavigationController 使用自定义代理,请将这些事件重定向到 tabBarController,否则 hidesBottomBarWhenPushed 和其他显示功能将不会工作。
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
//
navigationController.tab.controller?.navigationController(navigationController, willShow: viewController, animated: animated)
}
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
//
navigationController.tab.controller?.navigationController(navigationController, didShow: viewController, animated: animated)
}
自定义
创建一个 UIView 类,并让它继承自 TabBarProtocol
import TabBarController
class YourTabBar: UIView, TabBarProtocol {
weak var delegate: TabBarDelegate?
func setItems(_ items: [UITabBarItem]?, animated: Bool) {
// Update view
}
func setSelectedItem(_ item: UITabBarItem?, animated: Bool) {
// Update view
}
}
查看 SpringboardTabBar.swift 示例
Storyboard
在 storyboard 中将 TabBarController 的 tabBar 输出链接到您的自定义 tabBar
通过编程的方式
let tabBar = YourTabBar()
let tabBarController = TabBarController(viewControllers: [...], tabBar: tabBar)
高级自定义
锚点
TabBarController 支持四个用于 TabBar 的锚点
- top: tvOS 风格
- bottom: iOS 风格
- left
- right
Storyboard
设置您的 TabBarController 的 tabBarAnchorIndex 属性(0:顶部,1:底部,2:左侧,3:右侧)
编程式
let tabBar = YourTabBar()
let anchor: TabBarAnchor = .top
let tabBarController = TabBarController(viewControllers: [...], tabBar: tabBar, anchor: anchor)
TabBar
class YourTabBar: UIView, TabBarProtocol {
var additionalInset: CGFloat { return 0 } // positive or negative value
func setAnchor(_ anchor: TabBarAnchor) {
// Update view
}
func setTabBarHidden(_ hidden: Bool) {
// Update view
}
}
Animator
TabBarProtocol 提供了可选方法,允许您自定义 TabBar 的动画和帧。
class YourTabBar: UIView, TabBarProtocol {
func animator() -> TabBarAnimator? {
return YourTabBarAnimator()
}
}
class YourTabBarAnimator: TabBarAnimator {
func tabBarInsets(withContext context: TabBarAnimatorContext) -> UIEdgeInsets {
// return additional insets below your TabBar
}
func animateTabBar(using context: TabBarAnimatorContext) {
// Animate and update frame of the TabBar
UIView.animate(duration: 0.3, animations: {
context.tabBar.frame = finalFrame // update frame
context.animate() // animate insets updates
}, completion: context.completeTransition) // call completeTransition
}
}
请参阅 TabBarAnimator.swift
转换
如果您想在 TabBarController 上使用自定义动画,您必须使其继承自 TabBarControllerDelegate
extension YourTabBarController: TabBarControllerDelegate {
func tabBarController(_ tabBarController: TabBarController, animationControllerFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
// return your custom UIViewControllerAnimatedTransitioning
}
}
请参阅 SpringboardTabBarController.swift 示例
早于 iOS 11 支持
TabBarController 优化了 iOS 11 和 safeArea,如果您想支持 iOS 9 和 10,您需要使用额外的内边距。该库提供了不同的实现方式。
TabBar 顶部/底部内边距约束
TabBarChildControllerProtocol 提供了两个可选属性,允许您轻松管理 TabBar 内边距
var tabBarTopInsetConstraint: NSLayoutConstraint!
var tabBarBottomInsetConstraint: NSLayoutConstraint!
var tabBarLeadingInsetConstraint: NSLayoutConstraint!
var tabBarTrailingInsetConstraint: NSLayoutConstraint!
由于 UIViewController 继承自 TabBarChildControllerProtocol,只需将这些属性添加到您的类中(如果要在 Interface Builder 中使用它们,请使用 IBOutlet)
查看iOS9ViewController.swift示例
更新 TabBar 内边距
如果您想在 UIScrollView 上添加内边距而不是直接更新其框架,可以使用此方法处理
func updateTabBarInsets(_ insets: UIEdgeInsets) {
self.tableView.contentInset.bottom = insets.bottom
self.tableView.scrollIndicatorInsets.bottom = insets.bottom
}
查看iOS9TableViewController.swift示例
作者
Arnaud Dorgans, [email protected]
许可
TabBarController 可在 MIT 许可下使用。更多信息请参阅 LICENSE 文件。