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?