XZNavigationController 1.3.1

XZNavigationController 1.3.1

Xezun 维护。



  • Xezun

XZNavigationController

CI Status Version License Platform

XZNavigationController 为原生的 UINavigationController 组件拓展了自定义导航条的功能,并且与原生导航条兼容。

功能特色

一、面向协议

要开启自定义导航条支持,UINavigationController 只需遵循 XZNavigationController 协议即可,无需改变基类,不会带来额外风险。

// 让您的控制器遵循协议,即可获得自定义导航栏开关属性
class ExampleNavigationController: UINavigationController, XZNavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // 打开自定义导航栏开关
        self.isNavigationBarCustomizable = true
    }
    
}

二、自定义导航条

仅需视图遵循 XZNavigationBarProtocol 协议,即可作为控制器的自定义导航条。为了方便开发,框架内置了 XZNavigationBar 基类,以此进行开发,自定义导航条更简单。

框架默认不会提供自定义导航条,基类 XZNavigationBar 只是一个开发选项,自定义导航条仅需要遵循协议即可,并非必须以它为基类。

以下示例代码中,

public class ExampleNavigationBar: XZNavigationBar {
    
    public var title: String? {
        get {
            return (self.titleView as? UILabel)?.text
        }
        set {
            if titleView == nil {
                // 1. 配置 titleLabel 和 largeTitleLabel
                ...
                
                // 2. largeTitleLabel 可以直接作为 largeTitleView,但示例中,为了要实现覆盖的效果额外增加一个容器视图
                let largeTitleView = UIView.init(frame: CGRect(x: 0, y: 0, width: width, height: 52))
                largeTitleView.addSubview(largeTitleLabel)
                
                // 3. 使用 XZNavigationBar 只需要赋值 titleView 和 largeTitleView 即可,布局会自动进行
                self.titleView = titleLabel
                self.largeTitleView = largeTitleView
            } 
            titleLabel.text = newValue
            largeTitleLabel.text = newValue
        }
    }
    
    private let titleLabel = UILabel.init()
    private let largeTitleLabel = UILabel.init()
}

XZNavigationBar 已实现了 XZNavigationBarProtocol 协议,因此不需要额外实现。不过 XZNavigationBarProtocol 协议的实现并不复杂,只需定义两个属性即可,这两个属性会影响导航条布局,因此需要额外实现。

public protocol XZNavigationBarProtocol: UIView {
    var isTranslucent: Bool { get set }
    var prefersLargeTitles: Bool { get set }
}

三、使用自定义导航条

在控制器中使用自定义导航条,仅需控制器实现 XZNavigationBarCustomizable 协议即可。

public protocol XZNavigationBarCustomizable: UIViewController {
    var navigationBarIfLoaded: XZNavigationBarProtocol? { get }
}

没错这个协议,仅需实现一个属性。这个属性实际上是告诉框架,控制器创建了自定义导航条后,框架要通过哪个属性去获取它。

利用 Swift 面向协议的特性,我们可以创建一个拓展,使遵循协议的控制器自动获得统一的自定义导航条。

extension XZNavigationBarCustomizable {
    
    public var navigationBarIfLoaded: XZNavigationBarProtocol? {
        return self.navigationBar
    }
    
    public var navigationBar: ExampleNavigationBar {
        if let navigationBar = objc_getAssociatedObject(self, &_navigationBar) as? ExampleNavigationBar {
            return navigationBar
        }
        let navigationBar = ExampleNavigationBar(for: self, frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 0))
        objc_setAssociatedObject(self, &_navigationBar, navigationBar, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        return navigationBar
    }
}

这样在控制器中我们就可以直接使用了。

class ExampleLastViewController: UITableViewController, XZNavigationBarCustomizable {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationBar.title = "尾页"
        self.navigationBar.barTintColor = .systemBrown
    }
}

示例中我们直接使用的是 navigationBar 属性,而不是 XZNavigationBarCustomizable 协议中的 navigationBarIfLoaded 属性,这是因为 IfLoaded 是一个泛型对象,在上面的拓展中,我们用具体的 navigationBar 类型进行中转,这样我们就不需要进行类型转换了。

四、全屏手势导航

原生 UINavigationController 对手势返回的使用条件比较苛刻,因此 XZNavigationController 改进了这一功能。

  1. 默认情况下始终支持手势返回。
  2. 支持手势导航前进到下一个页面。
  3. 支持手势导航返回到任意页面。
  4. 支持限制导航行为。

要支持上述功能,只需遵循 XZNavigationGestureDrivable 协议即可。

public protocol XZNavigationGestureDrivable: UIViewController {
    
    func navigationController(_ navigationController: UINavigationController, edgeInsetsForGestureNavigation operation: UINavigationController.Operation) -> NSDirectionalEdgeInsets?
    
    func navigationController(_ navigationController: UINavigationController, viewControllerForGestureNavigation operation: UINavigationController.Operation) -> UIViewController?
    
}

协议的第一个方法通过控制边距即可控制手势导航是否触发;实现第二个方法则可以在手势导航时,跳转到任何页面;具体可以在代码中查看方法注释。

示例

要运行示例项目,请先从仓库中克隆,然后再从 Pods 目录运行 pod install

必须满足以下要求

iOS 11.0, Xcode 14.0

安装

XZNavigationController 通过 CocoaPods 可用。要安装它,只需在 Podfile 中添加以下行即可

pod 'XZNavigationController'

功能特性

作者

Xezun, [email protected]

许可证

XZNavigationController 基于 MIT 许可证。有关更多信息,请参阅 LICENSE 文件。