iOS 10 barTintColor animation

后端 未结 2 1471
被撕碎了的回忆
被撕碎了的回忆 2021-02-08 09:11

I\'ve noticed a change in the way bar tint color animates in ios 10. I\'ve created a sample project outlining the change: Github: ios10BarTintDemo

Basically on ios 9 the

相关标签:
2条回答
  • 2021-02-08 09:49

    You can fix this popping issue by adding something similar to this, running it in viewWillDisappear won't work for some reason in iOS10

    override func willMove(toParentViewController parent: UIViewController?) {
        self.navigationController?.navigationBar.barTintColor = UIColor.red
        super.willMove(toParentViewController: parent)
    }
    
    0 讨论(0)
  • 2021-02-08 10:04

    UPDATE

    I've tested in iOS 10.3 and I think the problem was fixed. And transitionCordinator is no need anymore. I think the animation is smooth. Please check my project on github or look at this code:

    class ViewControllerA: UIViewController {
    
        override func loadView() {
            super.loadView()
            title = "A"
            view.backgroundColor = .white
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "NEXT", style: .plain, target: self, action: #selector(self.showController))
        }
    
        override func viewWillAppear(_ animated: Bool) {
            setColors()
            super.viewWillAppear(animated)
        }
    
        func showController() {
            navigationController?.pushViewController(ViewControllerB(), animated: true)
        }
    
        private func setColors() {
            navigationController?.navigationBar.tintColor = .black
            navigationController?.navigationBar.barTintColor = .red
            navigationController?.navigationBar.isTranslucent = false
        }
    }
    
    
    
    
    class ViewControllerB: UIViewController {
    
        override func loadView() {
            super.loadView()
            title = "B"
            view.backgroundColor = .white
        }
    
        override func viewWillAppear(_ animated: Bool) {
            setColors()
            super.viewWillAppear(animated)
        }
    
        override func willMove(toParentViewController parent: UIViewController?) {
            if parent == nil {
                navigationController?.navigationBar.barTintColor = .red
            }
            super.willMove(toParentViewController: parent)
        }
    
    
        private func setColors() {
            navigationController?.navigationBar.tintColor = .black
            navigationController?.navigationBar.barTintColor = .blue
            navigationController?.navigationBar.isTranslucent = false
        }
    }
    

    ============================================================================================================================================================================================================================================================================================================

    To achieve this kind of animation you should use UIViewControllerTransitionCoordinator as Apple documentation say it is :

    An object that adopts the UIViewControllerTransitionCoordinator protocol provides support for animations associated with a view controller transition.(...)

    So every UIViewController has own transitionController. To get this you should call in the UIViewControllerClass :

    self.transitionCoordinator()

    From documentation:

    Returns the active transition coordinator object.

    So to get the result that you want you should implement animateAlongsideTransition method in viewController transitionCoordinatior. Animation works when you click backButton and swipe to back.

    Example :

    First Controller :

    class ViewControllerA: UIViewController {
    
        override func loadView() {
            super.loadView()
            title = "A"
            view.backgroundColor = .white
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "NEXT", style: .plain, target: self, action: #selector(self.showController))
            setColors()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            animate()
        }
    
        func showController() {
            navigationController?.pushViewController(ViewControllerB(), animated: true)
        }
    
        private func animate() {
            guard let coordinator = self.transitionCoordinator else {
                return
            }
    
            coordinator.animate(alongsideTransition: {
                [weak self] context in
                self?.setColors()
            }, completion: nil)
        }
    
        private func setColors() {
            navigationController?.navigationBar.tintColor = .black
            navigationController?.navigationBar.barTintColor = .red
        }
    }
    

    Second Controller:

    class ViewControllerB : UIViewController {
    
        override func loadView() {
            super.loadView()
            title = "B"
            view.backgroundColor = .white
            setColors()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            animate()
        }
    
        override func willMove(toParentViewController parent: UIViewController?) { // tricky part in iOS 10
            navigationController?.navigationBar.barTintColor = .red //previous color
            super.willMove(toParentViewController: parent)
        }
    
        override func viewDidAppear(_ animated: Bool) {
            navigationController?.navigationBar.barTintColor = .blue
        }
    
        private func animate() {
            guard let coordinator = self.transitionCoordinator else {
                return
            }
            coordinator.animate(alongsideTransition: {
                [weak self] context in
                self?.setColors()
            }, completion: nil)
        }
    
        private func setColors(){
            navigationController?.navigationBar.tintColor = .black
            navigationController?.navigationBar.barTintColor = .blue
        }
    
    }
    

    UPDATE iOS 10

    In the iOS 10 the tricky part is to add the willMoveTo(parentViewController parent: UIViewController?) in the second ViewController. And set the navigationBar tintColor to the color value of previous controller. Also, in viewDidAppear method in second ViewControler set the navigationBar.tintColor to the color from second viewController.

    Check out my example project on github

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