UINavigationBar在推送时改变颜色

Vas*_*ily 22 uinavigationbar uinavigationcontroller ios swift

UINavigationBar在不同的视图中使用了2种不同的条纹色调.我在两个视图中都用这种方法改变了颜色:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.barTintColor = COLOR
}
Run Code Online (Sandbox Code Playgroud)

当我点击后退按钮时,颜色没有顺利改变(你可以看到最后一秒闪烁).

视觉错误

但是如果只是向后滑动视图而不是点击后退按钮,一切都会好的.

没有视觉错误

如何在两种情况下顺利过渡?

kam*_*soc 19

为了实现这种动画,你应该使用的UIViewControllerTransitionCoordinator苹果的文件说,这是:

采用UIViewControllerTransitionCoordinator协议的对象为与视图控制器转换关联的动画提供支持.(...)

所以每个人UIViewController都拥有transitionController.要得到这个,你应该打电话给UIViewControllerClass:

self.transitionCoordinator()

来自文档:

返回活动的转换协调器对象.

因此,要获得您想要的结果,您应该animateAlongsideTransition在viewController transitionCoordinatior中实现方法.单击backButton并向后滑动即可使用动画.

示例:

navigation_bar_animation

第一控制员:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

第二控制器:

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) {
        super.viewDidAppear(animated)
        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
    }

}
Run Code Online (Sandbox Code Playgroud)

更新iOS 10

在iOS 10中,棘手的部分是willMoveTo(parentViewController parent: UIViewController?)第二个 ViewController中添加.并将navigationBar设置tintColor上一个控制器的颜色值.另外,在第二个 ViewControler 中的viewDidAppear方法中,设置第二个 viewController 的颜色.navigationBar.tintColor

在github上查看我的示例项目


Vas*_*ily 14

我编写了最终解决方案,看起来最舒服(不需要在自己的视图控制器中使用很多覆盖).它在iOS 10上完美运行,易于用于自己的目的.

GitHub上

您可以查看GitHub Gist的完整类代码和更详细的指南,我不会在此发布完整代码,因为Stackoverflow不用于存储大量代码.

用法

下载GitHub的Swift文件.为了使其工作,只需使用ColorableNavigationController代替UINavigationController并采用所需的子视图控制器来NavigationBarColorable协议.

例:

class ViewControllerA: UIViewController, NavigationBarColorable {
    public var navigationBarTintColor: UIColor? { return UIColor.blue }

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Push", style: .plain, target: self, action: #selector(self.showController))
    }

    func showController() {
        navigationController?.pushViewController(ViewControllerB(), animated: true)
    }
}

class ViewControllerB: UIViewController, NavigationBarColorable {
    public var navigationBarTintColor: UIColor? { return UIColor.red }
}

let navigationController = ColorableNavigationController(rootViewController: ViewControllerA())
Run Code Online (Sandbox Code Playgroud)