color bar ios swift uinavigationcontroller uinavigationbar

ios - navigationbar title color



UINavigationBar cambia los colores al empujar (4)

Estoy usando 2 colores de tinte de barra diferentes en UINavigationBar en diferentes vistas. Estoy cambiando de color con ese método en ambas vistas:

override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) self.navigationController?.navigationBar.barTintColor = COLOR }

Cuando toco el botón de atrás, el color no se modifica con suavidad (puedes ver parpadear en el último segundo).

Pero todo está bien si solo desliza la vista hacia atrás en lugar de tocar el botón Atrás.

¿Cómo hacer una transición suave en ambas situaciones?


Esto funcionó para mí:

override func willMove(toParent parent: UIViewController?) { super.willMove(toParent: parent) navigationController?.navigationBar.barTintColor = previous view controller''s navigation bar color }


He codificado la solución final que se ve más cómoda de usar (no es necesario usar muchas anulaciones en los propios controladores de vista). Funciona perfectamente en iOS 10 y es fácil de adoptar para propósitos propios.

GitHub

Puede consultar GitHub Gist para obtener el código de clase completo y una guía más detallada. No publicaré el código completo aquí porque no está diseñado para almacenar una gran cantidad de código.

Uso

Descargar archivo Swift para GitHub. Para que funcione, simplemente use ColorableNavigationController lugar de UINavigationController y adopte los controladores de vista secundarios necesarios para el protocolo NavigationBarColorable .

Ejemplo:

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())


Para lograr este tipo de animación, debe utilizar UIViewControllerTransitionCoordinator ya que la documentación de Apple dice que es:

Un objeto que adopta el protocolo UIViewControllerTransitionCoordinator proporciona soporte para animaciones asociadas con una transición de controlador de vista. (...)

Así que cada UIViewController tiene un UIViewController transitionController propio. Para obtener esto, debe llamar a UIViewControllerClass :

self.transitionCoordinator()

De la documentation :

Devuelve el objeto coordinador de transición activo.

Entonces, para obtener el resultado que desea, debe implementar el método animateAlongsideTransition en viewController transitionCoordinatior. La animación funciona cuando se hace clic en el botón backButton y se desliza hacia atrás.

Ejemplo:

Primer controlador:

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

Segundo controlador:

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

ACTUALIZAR iOS 10

En el iOS 10, la parte difícil es agregar el willMoveTo(parentViewController parent: UIViewController?) En el segundo ViewController. Y configure la tintColor navegación tintColor al valor de color del controlador anterior . Además, en el método viewDidAppear en el segundo ViewControler, configure la barra de navigationBar.tintColor al color del segundo viewController.

Mira mi proyecto de ejemplo en github


Simplemente me estaba preguntando. Para el mismo propósito yo uso UINavigationControllerDelegate . En navigationController(_:willShow:) empiezo la animación transitionCoordinator?.animate(alongsideTransition:completion:) . Funciona muy bien al presionar nuevos controladores, sin embargo, el pop no lo hace.

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { let dst = viewController as! ViewController guard animated else { navigationController.navigationBar.barTintColor = dst.navigationBarColor navigationController.navigationBar.tintColor = dst.tintColor navigationController.navigationBar.barStyle = dst.barStyle return } navigationController.transitionCoordinator?.animate(alongsideTransition: { context in navigationController.navigationBar.barTintColor = dst.navigationBarColor navigationController.navigationBar.tintColor = dst.tintColor navigationController.navigationBar.barStyle = dst.barStyle }, completion: { context in if context.isCancelled { let source = context.viewController(forKey: UITransitionContextViewControllerKey.from) as! ViewController navigationController.navigationBar.barTintColor = source.navigationBarColor navigationController.navigationBar.tintColor = source.tintColor navigationController.navigationBar.barStyle = source.barStyle } })

¿Ves alguna razón por la que debería funcionar con push pero no pops?