TabBarController 1.0.1

TabBarController 1.0.1

Arnaud Dorgans 维护。



TabBarController

CI Status Version License Platform

当你发现最新的 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 文件。