Geen omschrijving

NavigationController.swift 5.2KB

    // // NavigationController.swift // PaiaiUIKit // // Created by FFIB on 2019/4/23. // Copyright © 2019 FFIB. All rights reserved. // import UIKit public class NavigationController: UINavigationController { private var operation: Operation = .none private var barConfigures: [UIViewController?: NavigationBarConfiguration] = [:] private var _fromFakeBar = UIToolbar() private var _toFakeBar = UIToolbar() override public init(rootViewController: UIViewController) { super.init(navigationBarClass: NavigationBar.classForCoder(), toolbarClass: nil) self.viewControllers = [rootViewController] } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } override public func viewDidLoad() { super.viewDidLoad() delegate = self interactivePopGestureRecognizer?.delegate = self interactivePopGestureRecognizer?.isEnabled = true } public override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if operation == .none { return } navigationBar.getBarBackground()?.alpha = 0 } } fileprivate extension NavigationController { func setFakeNavigationBar() { UIView.setAnimationsEnabled(false) guard let to = transitionCoordinator?.viewController(forKey: .to), let from = transitionCoordinator?.viewController(forKey: .from) else { return } switch self.operation { case .push: barConfigures[to] = NavigationBarConfiguration(navigationBar: navigationBar) case .pop: navigationBar.setBackgroundImage(barConfigures[to]?.backgroundImage, for: .default) default: break } setToFakeNavigationBar(for: to) setFromFakeNavigationBar(for: from) navigationBar.apply(for: .transparent) UIView.setAnimationsEnabled(true) if barConfigures[to]?.isHidden != barConfigures[from]?.isHidden { setNavigationBarHidden(barConfigures[to]?.isHidden ?? false, animated: true) } } func setFromFakeNavigationBar(for from: UIViewController) { if let navBarFrame = from.getFakeBarFrame(for: navigationBar) { _fromFakeBar = UIToolbar(configure: barConfigures[from] ?? .default) _fromFakeBar.delegate = self _fromFakeBar.frame = navBarFrame from.view.addSubview(_fromFakeBar) } } func setToFakeNavigationBar(for to: UIViewController) { if let navBarFrame = to.getFakeBarFrame(for: navigationBar) { _toFakeBar = UIToolbar(configure: barConfigures[to] ?? .default) _toFakeBar.delegate = self _toFakeBar.frame = navBarFrame to.view.addSubview(_toFakeBar) } } func clearFake() { _fromFakeBar.removeFromSuperview() _toFakeBar.removeFromSuperview() guard let from = transitionCoordinator?.viewController(forKey: .from), operation == .pop else { return } barConfigures.removeValue(forKey: from) } } extension NavigationController: UINavigationControllerDelegate { public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { self.operation = operation return nil } public func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { if operation == .none { self.barConfigures[viewController] = NavigationBarConfiguration(navigationBar: navigationBar) return } transitionCoordinator?.animate(alongsideTransition: { context in if context.isInteractive { self.operation = .pop } self.setFakeNavigationBar() }, completion: { context in let vc: UIViewController? if context.isCancelled { self.operation = .push vc = context.viewController(forKey: .from) } else { vc = context.viewController(forKey: .to) } self.navigationBar.getBarBackground()?.alpha = 1 self.navigationBar.apply(for: self.barConfigures[vc] ?? .default) self.clearFake() }) } } extension NavigationController: UIGestureRecognizerDelegate { public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { if gestureRecognizer == interactivePopGestureRecognizer { return viewControllers.count > 1 } return true } } extension NavigationController: UIToolbarDelegate { public func position(for bar: UIBarPositioning) -> UIBarPosition { return .top } }