Animate navigation bar barTintColor change in iOS10 not working

后端 未结 2 2029
梦谈多话
梦谈多话 2021-02-20 07:31

I upgraded to XCode 8.0 / iOS 10 and now the color change animation of my navigation bar is not working anymore, it changes the color directly without any animation.

<         


        
2条回答
  •  我在风中等你
    2021-02-20 07:54

    Interactive animation

    Define a protocol:

    /// Navigation bar colors for `ColorableNavigationController`, called on `push` & `pop` actions
    public protocol NavigationBarColorable: UIViewController {
        var navigationTintColor: UIColor? { get }
        var navigationBarTintColor: UIColor? { get }
    }
    
    public extension NavigationBarColorable {
        var navigationTintColor: UIColor? { return nil }
    }
    

    Define a custom NavigationController subclass:

    class AppNavigationController: UINavigationController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            navigationBar.shadowImage = UIImage()
            if let colors = rootViewController as? NavigationBarColorable {
                setNavigationBarColors(colors)            
            }
        }
        
        private var previousViewController: UIViewController? {
            guard viewControllers.count > 1 else {
                return nil
            }
            return viewControllers[viewControllers.count - 2]
        }
        
        override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
            if let colors = viewController as? NavigationBarColorable {
                setNavigationBarColors(colors)
            }
                   
            super.pushViewController(viewController, animated: animated)
        }
        
        override open func popViewController(animated: Bool) -> UIViewController? {
            if let colors = previousViewController as? NavigationBarColorable {
                setNavigationBarColors(colors)
            }
                            
            // Let's start pop action or we can't get transitionCoordinator()
            let popViewController = super.popViewController(animated: animated)
            
            // Secure situation if user cancelled transition
            transitionCoordinator?.animate(alongsideTransition: nil, completion: { [weak self] context in
                guard let `self` = self else { return }
    
                guard let colors = self.topViewController as? NavigationBarColorable else { return }
                self.setNavigationBarColors(colors)
            })
            
            return popViewController
        }
        
        override func popToRootViewController(animated: Bool) -> [UIViewController]? {
            if let colors = rootViewController as? NavigationBarColorable {
                setNavigationBarColors(colors)
            }
            
            let controllers = super.popToRootViewController(animated: animated)
            
            return controllers
        }
        
        private func setNavigationBarColors(_ colors: NavigationBarColorable) {
            
            if let tintColor = colors.navigationTintColor {
                navigationBar.titleTextAttributes = [
                    .foregroundColor : tintColor
                ]
                navigationBar.tintColor = tintColor
            }
            
            navigationBar.barTintColor = colors.navigationBarTintColor
        }
    }
    

    Now you can conform to NavigationBarColorable in any controller inside the AppNavigationController and give it any color you want.

    extension FirstViewController: NavigationBarColorable {
        public var navigationBarTintColor: UIColor? { UIColor.red }
        public var navigationTintColor: UIColor? { UIColor.white }
    }
    
    extension SecondViewController: NavigationBarColorable {
        public var navigationBarTintColor: UIColor? { UIColor.blue }
        public var navigationTintColor: UIColor? { UIColor.orange }
    }
    

    Don't forget to implement this useful extension:

    extension UINavigationController {
        var rootViewController: UIViewController? {
            return viewControllers.first
        }
    }
    

提交回复
热议问题