Das Verhalten der UINavigationBar beim Durchlaufen des Stapels kann unvorhersehbar und häufig fehlerhaft erscheinen. Aber tatsächlich ist es das! Dieser Artikel soll das Wissen über die Arbeitsprinzipien auffrischen und die Möglichkeiten zur Anpassung des Verhaltens aufzeigen.
Eine allgemeine Theorie
Wenn Sie sich auskennen, können Sie direkt zur Animation scrollen.
UINavigationBar ist eine Ansicht. Normalerweise wird seine Position vom UINavigationController gesteuert, aber wie bei anderen Ansichten können Sie ihn selbst verwenden.
UINavigationItem ist eine Klasse, die den Status (ähnlich dem viewModel) für die UINavigationBar-Konfiguration beschreibt. Nur eine Klasse mit Eigenschaften, die an die UINavigationBar übergeben werden.
Die UINavigationBar enthält ein Array [UINavigationItem]. Mit den Methoden pushItem, popItem und setItems können Sie den Übergang von einem UINavigationBar-Status in einen anderen animieren.
Jeder UIViewController enthält ein UINavigationItem. Der UINavigationController selbst verwaltet das Hinzufügen dieser Eigenschaft zum Stapel von UINavigationBar-Elementen.
Weitere Details finden Sie hier:
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 = trueUINavigationController 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/