que life change ios uiview uiviewcontroller

ios - life - view controller que es



¿Cómo hago la transición/animar el color de UINavigationBar? (2)

He estado buscando cómo hacer la transición / animación del barTintColor de UINavigationBar por un tiempo, y solo veo diferentes respuestas. Algunos usan UIView.animateWithDuration , algunos usan CATransition , pero los más interesantes, como este, usan animate(alongsideTransition animation.. CATransition animate(alongsideTransition animation.. , a la que me gusta el sonido, pero no puedo hacer que funcione correctamente. ¿Estoy haciendo algo mal?

Muchos especifican que simplemente puedo usar transitionCoordinator en viewWillAppear: He creado un nuevo proyecto súper pequeño como este:

class RootViewController:UIViewController{ //Only subclassed override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in self?.setNavigationColors() }, completion: nil) } func setNavigationColors(){ //Override in subclasses } } class FirstViewController: RootViewController { override func viewDidLoad() { super.viewDidLoad() self.title = "First" } override func setNavigationColors(){ navigationController?.navigationBar.barTintColor = UIColor.white navigationController?.navigationBar.tintColor = UIColor.black navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.black] navigationController?.navigationBar.barStyle = UIBarStyle.default } } class SecondViewController: RootViewController { override func viewDidLoad() { super.viewDidLoad() self.title = "Second" } override func setNavigationColors(){ navigationController?.navigationBar.barTintColor = UIColor.black navigationController?.navigationBar.tintColor = UIColor.white navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white] navigationController?.navigationBar.barStyle = UIBarStyle.black } }

Con este código, esto sucede:

  • La transición de empuje de First a Second parece perfecta. Todos los elementos cambian perfectamente, tal vez excepto StatusBar, que cambia instantáneamente a blanco. Prefiero saber cómo hacer la transición, pero lo aceptaré por ahora.
  • La transición de Second a First está completamente equivocada. Mantiene los colores de Second hasta que la transición esté completa.
  • La transición de arrastre del Second al First ve bien, al arrastrar todo el camino. Una vez más, el StatusBar se vuelve negro inmediatamente tan pronto como empiezo a arrastrar, pero no sé si eso es posible solucionarlo.
  • La transición de arrastre del Second al First pero cancelada a mitad del arrastre y volviendo al Second está completamente arruinada. Se ve bien hasta que Second recupera completamente el control, y luego cambia de repente a First -colors. Esto no debería suceder.

Hice algunos cambios en mi RootViewController para hacerlo un poco mejor. viewWillAppear: completamente y lo cambié con esto:

class RootViewController:UIViewController{ override func willMove(toParentViewController parent: UIViewController?) { if let last = self.navigationController?.viewControllers.last as? RootViewController{ if last == self && self.navigationController!.viewControllers.count > 1{ if let parent = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - 2] as? RootViewController{ parent.setNavigationColors() } } } } override func viewWillDisappear(_ animated: Bool) { if let parent = navigationController?.viewControllers.last as? RootViewController{ parent.animateNavigationColors() } } override func viewDidAppear(_ animated: Bool) { self.setNavigationColors() } func animateNavigationColors(){ transitionCoordinator?.animate(alongsideTransition: { [weak self](context) in self?.setNavigationColors() }, completion: nil) } func setNavigationColors(){ //Override in subclasses } }

Con este código actualizado, obtengo esto:

Algunas observaciones:

  • La transición de First a Second es la misma
  • La transición de pop de Second a First ahora se está animando correctamente, excepto desde la flecha de retroceso, el texto de fondo (y la barra de estado, pero sí ...). Estos se cambian al instante a negro. En el primer gif, se podía ver que la flecha hacia atrás y el texto hacia atrás también transitaban.
  • La transición de arrastre de la Second a la First también tiene este problema, la flecha de retroceso y el texto de atrás repentinamente son instantáneamente negros al comenzar. El barTint es fijo para que no tenga un color incorrecto al cancelar el arrastre.

¿Qué estoy haciendo mal? ¿Cómo se supone que haga esto?

Lo que quiero es hacer la transición de todos los elementos sin problemas. El tinte del botón de retroceso, el texto de fondo, el título, barTint y la barra de estado. ¿No es esto posible?


Puede sobrescribir los métodos push y pop de UINavigationController para establecer el color de la barra. He almacenado el color de la barra correspondiente a un controlador de vista en su elemento de navegación con una subclase personalizada de UINavigationItem . El siguiente código funciona para mí en iOS 11 para transiciones completas y también para interactivas:

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

Nota: La coordinación de la animación de color se realiza por el controlador de navegación


en 10 iOS funciona imperfectamente :(

Subclase su controlador de navegación para usar el estilo de barra de estado del controlador de vista visible:

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

Anule preferredStatusBarStyle en el controlador raíz y agregue la función para establecer los estilos antes de la animación pop:

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 }

En primer controlador:

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 }

En segundo:

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 }

Proyecto de ejemplo: https://github.com/josshad/TestNavBarTransition