El comportamiento de UINavigationBar cuando se navega por la pila puede parecer impredecible y, a menudo, con errores. ¡Pero, de hecho, lo es! Este artículo tiene como objetivo refrescar su conocimiento de los principios del trabajo y mostrar las posibilidades de personalizar el comportamiento.
Alguna teoría general
Si tiene conocimientos, no dude en desplazarse directamente a la animación.
UINavigationBar es una vista. Normalmente, su posición está controlada por UINavigationController, pero al igual que otras vistas, puede usarlo usted mismo.
UINavigationItem es una clase que describe el estado (similar al viewModel) para la configuración de UINavigationBar. Solo una clase con propiedades que se pasarán a UINavigationBar.
UINavigationBar contiene una matriz [UINavigationItem]. Con los métodos pushItem, popItem y setItems, puede animar la transición de un estado UINavigationBar a otro.
Cada UIViewController contiene un UINavigationItem. El propio UINavigationController administra la adición de esta propiedad a la pila de elementos UINavigationBar.
Más detalles se pueden encontrar aquí:
https://developer.apple.com/documentation/uikit/uinavigationbar
https://developer.apple.com/documentation/uikit/uinavigationitem
UINavigationBar . :
prompt ( )
largeTitleDisplayMode
UINavigationBar – view, – , , .
: – navigationBar.backgroundColor, – navigationBar.barTintColor.
– backgroundColor. , backgroundColor – view -.
prompt- .
, transition UINavigationBar . UIViewControllerAnimatedTransitioning UINavigationBar.
: , .
safeArea . additionalSafeAreaInsets UIViewController- :
contentView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
UINavigationController UINavigationControllerDelegate. , .
class NavigationController: UINavigationController, UINavigationControllerDelegate { }
UINavigationController-.
navigationController.delegate = navigationController
. UIViewController navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) transitionCoordinator safeArea.
guard let fromViewController = viewController.transitionCoordinator?.viewController(forKey: .from)
else { return }
// . , , pop
let isPopped = !navigationController.viewControllers.contains(fromViewController)
// ,
viewController.transitionCoordinator?.animate { context in
guard let from = context.viewController(forKey: .from),
let to = context.viewController(forKey: .to)
else { return }
//
// , safeArea
//
UIView.setAnimationsEnabled(false)
let diff = to.view.safeAreaInsets.top - from.view.safeAreaInsets.top
//
to.additionalSafeAreaInsets.top = -diff
to.view.layoutIfNeeded()
UIView.setAnimationsEnabled(true)
// safeArea
to.additionalSafeAreaInsets.top = 0
to.view.layoutIfNeeded()
guard isPopped else { return }
// pop-
// additionalSafeAreaInsets
from.view.frame.origin.y = diff
from.view.frame.size.height += max(0, -diff)
} completion: { context in
guard let from = context.viewController(forKey: .from),
let to = context.viewController(forKey: .to)
else { return }
from.additionalSafeAreaInsets.top = 0
to.additionalSafeAreaInsets.top = 0
}
, :
– . , UINavigationBar. , , .
, :)
: Rtishchev Evgenii https://twitter.com/katleta3000/status/1259400743771156480
navigation bar: https://www.programmersought.com/article/1594185256/