How to use standalone UINavigationBar in iOS
Issue #144
There are times we want the same UIViewController to look good when it’s presented modally or pushed from UINavigationController stack. Take a look at BarcodeScanner and the PR https://github.com/hyperoslo/BarcodeScanner/pull/82
When it is presented, we need a header view so that we can show a title and a close button. We can create a custom HeaderView that inherits from UIView or either embed it in a UINavigationController before presenting.
If we go with the controller being embedded in UINavigationController approach, it will collide with the other UINavigationController when it is pushed.
If we go with custom HeaderView, then we need to layout the view so that it looks good on both portrait and landscape, and on iPhone X that as safeAreaLayoutGuide.
Using standalone UINavigationBar
Since UINavigationController uses UINavigationBar under the hood, which uses UINavigationItem info to present the content. We can imitate this behavior by using a standalone UINavigationBar. See Adding Content to a Standalone Navigation Bar
In the vast majority of scenarios you will use a navigation bar as part of a navigation controller. However, there are situations for which you might want to use the navigation bar UI and implement your own approach to content navigation. In these situations, you can use a standalone navigation bar.
A navigation bar manages a stack of UINavigationItem objects
The beauty is that our standalone UINavigationBar and that of UINavigationController are the same, use the same UINavigationItem and no manual layout are needed
Declare UINavigationItem
We can just set properties like we did with a normal navigationItem
1 | let standaloneItem = UINavigationItem() |
Adding UINavigationBar
Customise your bar, then declare layout constraints. You only need to pin left, right, and top. Note that you need to implement UINavigationBarDelegate to attach bar to status bar, so that it appears good on iPhone X too
1 | let navigationBar = UINavigationBar() |
1 | extension BarcodeScannerController: UINavigationBarDelegate { |
Inside UINavigationController
When this UIViewController is pushed from a UINavigationController stack, we just need to hide our standalone navigationBar. If we prefer the default back button, we don’t need to set leftBarButtonItem
On iOS 10, you need to call sizeToFit for any items in UINavigationItem for it to get actual size
1 | override func viewWillAppear(_ animated: Bool) { |