How do I transition/animate color of UINavigationBar?

前端 未结 2 508
再見小時候
再見小時候 2021-02-01 02:52

I have been searching for how to transition/animate the barTintColor of a UINavigationBar for a while now, and I only see different answers. Some use <

相关标签:
2条回答
  • 2021-02-01 03:28

    in 10 iOS it works imperfectly :(

    Subclass your navigation controller to use statusbarstyle of visible view controller:

    class MyNavigationController: UINavigationController {
        override var preferredStatusBarStyle: UIStatusBarStyle {
            return visibleViewController!.preferredStatusBarStyle
        }
    }
    

    Override preferredStatusBarStyle in Root controller and add function to set styles before pop animation:

    private var _preferredStyle = UIStatusBarStyle.default;
    override var preferredStatusBarStyle: UIStatusBarStyle {
        get {
            return _preferredStyle
        }
        set {
            _preferredStyle = newValue
            self.setNeedsStatusBarAppearanceUpdate()
        }
    
    }
    
    
    func animateNavigationColors(){
            self.setBeforePopNavigationColors()
            transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in
                self?.setNavigationColors()
                }, completion: nil)
        }
    
    func setBeforePopNavigationColors() {
        //Override in subclasses
    }
    

    In first controller:

    override func setBeforePopNavigationColors() {
        navigationController?.navigationBar.tintColor = UIColor.white
        navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
        self.preferredStatusBarStyle = UIStatusBarStyle.lightContent
    }
    
    override func setNavigationColors(){
        navigationController?.navigationBar.barTintColor = UIColor.white
        navigationController?.navigationBar.tintColor = UIColor.black
        navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.black]
        navigationController?.navigationBar.barStyle = UIBarStyle.default
        self.preferredStatusBarStyle = UIStatusBarStyle.default
    }
    

    In second:

      override func setNavigationColors(){
            navigationController?.navigationBar.barTintColor = UIColor.black
            navigationController?.navigationBar.tintColor = UIColor.white
            navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
            navigationController?.navigationBar.barStyle = UIBarStyle.black
            self.preferredStatusBarStyle = UIStatusBarStyle.lightContent
        }
    

    Example project: https://github.com/josshad/TestNavBarTransition

    0 讨论(0)
  • 2021-02-01 03:48

    You can overwrite the push and pop methods of UINavigationController to set the bar color. I've stored the bar color corresponding to a view controller in its navigation item with a custom subclass of UINavigationItem. The following code works for me in iOS 11 for full and for interactive transitions as well:

    import UIKit
    
    class NavigationItem: UINavigationItem {
        @IBInspectable public var barTintColor: UIColor?
    }
    
    class NavigationController: UINavigationController, UIGestureRecognizerDelegate {
        func applyTint(_ navigationItem: UINavigationItem?) {
            if let item = navigationItem as? NavigationItem {
                self.navigationBar.barTintColor = item.barTintColor
            }
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            applyTint(self.topViewController?.navigationItem)
            self.interactivePopGestureRecognizer?.delegate = self
        }
        override func pushViewController(_ viewController: UIViewController, animated: Bool) {
            applyTint(viewController.navigationItem)
            super.pushViewController(viewController, animated: animated)
        }
    
        override func popViewController(animated: Bool) -> UIViewController? {
            let viewController = super.popViewController(animated: animated)
    
            applyTint(self.topViewController?.navigationItem)
            return viewController
        }
    
        override func popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? {
            let result = super.popToViewController(viewController, animated: animated)
    
            applyTint(viewController.navigationItem)
            return result
        }
    
        override func popToRootViewController(animated: Bool) -> [UIViewController]? {
            let result = super.popToRootViewController(animated: animated)
    
            applyTint(self.topViewController?.navigationItem)
            return result
        }
    
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true
        }
    
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return (otherGestureRecognizer is UIScreenEdgePanGestureRecognizer)
        }
    }
    

    Note: The coordination of the color animation is done by the navigation controller

    0 讨论(0)
提交回复
热议问题