123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- 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
- }
- }
|