Perilaku UINavigationBar saat menavigasi tumpukan bisa tampak tidak dapat diprediksi dan sering bermasalah. Tapi, nyatanya, itu benar! Artikel ini dimaksudkan untuk menyegarkan pengetahuan tentang prinsip kerja dan menunjukkan kemungkinan untuk menyesuaikan perilaku.
Beberapa teori umum
Jika Anda berpengetahuan luas, silakan gulir langsung ke animasi.
UINavigationBar adalah sebuah tampilan. Biasanya, posisinya dikontrol oleh UINavigationController, tetapi seperti tampilan lain, Anda dapat menggunakannya sendiri.
UINavigationItem adalah kelas yang mendeskripsikan status (mirip dengan viewModel) untuk konfigurasi UINavigationBar. Hanya kelas dengan properti yang akan diteruskan ke UINavigationBar.
UINavigationBar berisi larik [UINavigationItem]. Dengan menggunakan metode pushItem, popItem, dan setItems, Anda dapat menganimasikan transisi dari satu status UINavigationBar ke yang lain.
Setiap UIViewController berisi UINavigationItem. UINavigationController itu sendiri mengelola penambahan properti ini ke tumpukan item UINavigationBar.
Detail lebih lanjut dapat ditemukan di sini:
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/