Reputation: 462
I have 'about' controller using Navigation Bar below status bar. For some reason I have to set the background color of View to be the same color of Navigation bar, otherwise, the background of status bar will be white. This trick works fine on other device, but not on iPhoneX's landscape view. As you see below:
If I set the background of View to be white, there will be other issues:
2) Navigation bar is not extended on landscape view
Looks like this is an issue that I have Navigation Bar inside View as the storyboard structure shown below:
But I cannot seem to be able to move Navigation Bar to the same level as View. Any idea?
Upvotes: 4
Views: 9941
Reputation: 401
A summary and a little explanation for beginners for CodingMeSwiftly's answer:
In your ViewController class in viewDidLoad method or similar you must assign a delegate (or do it in storyboard):
navigationBar.delegate = self //where navigationBar is an IBOutlet
Make extension for your ViewController class:
extension ViewController: UINavigationBarDelegate { func position(for bar: UIBarPositioning) -> UIBarPosition { return .topAttached } }
Check that on the storyboard the Navigation Bar top constrain is Safe Area.Top
It works for me.
Upvotes: 1
Reputation: 1232
isTranslucent
is set by default to true
. Setting it to false
will extend the navigation bar below the status bar.
navigationBar.isTranslucent = false
Upvotes: 2
Reputation: 3261
Your UINavigationBar
is most likely pinned to the safeAreas of the view. There are several things to consider here:
Currently, your view is pinned to the safe area insets of its superview. On iPhone X, that is:
UIEdgeInsets(top: 44, left: 0, bottom: 34, right: 0)
in PortraitUIEdgeInsets(top: 0, left: 44, bottom: 21, right: 44)
in LandscapeSo this is exactly where your view ends up:
The values in safeAreaInsets.bottom
don't matter here, because the navigationBar will most likely not expand that far to the bottom of its superview.
Ok, now let's pin the view to the edges of its superview instead of to the safe area inset:
(Do that for all 3 edges, adjusting the constant to 0 if necessary)
This is what we end up with:
Looking good for landscape but what's up with portrait? Notice how the bar button sits inside the status bar.
Well, the layout system is doing exactly what you're telling it to do (if that were true all the time, coding for iOS would be a breeze :D). It pins the view to the very top of its superview, ignoring any layoutMargin
or safeAreaInsets
. For UINavigationBar
however, this is not what we want. We want the content of the bar to start at any safeAreaInset.top
, so that it does not interfere with the status bar, for example.
The solution is to revert the top constraint back to 'relative to safeArea'. The content of the navigationBar now looks ok. In order to expand the background of the navigationBar upwards, you set the navigationBars delegate (UINavigationBarDelegate
) and provide the following implementation:
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
By returning .topAttached
, you tell the navigationBar to expand its background (blur view) upwards beneath the status bar.
Result:
Note that in general, it would be better to use UINavigationController
if possible. This whole layout dance is done for you, plus adding a plain UINavigationBar
to a view won't work well with large titles. They need a navigationController providing the collapse and expand logic.
A few additional notes on this topic:
UINavigationBar
respects these and insets its content accordingly. It does not do so for vertical insets, that's why we have to do the dance described above.Preserve Superview Margins
for the navigation bar in the storyboard. Again, all these things are handled by the system for you if you simply use UINavigationController
in the first place. Upvotes: 14
Reputation: 302
You can use two views one for status bar and another for navigation bar and apply constraint as shown and your issue will be fixed.
Upvotes: 4
Reputation: 462
Looks like standalone Navigation Bar just does not work for this case. After change it to Navigation Item fixed the issue. To make it to be Navigation Item, I choose the existing controller (the one with Navigation Bar) and embed it into Navigation Controller via "Editor -> Embed".
Upvotes: -1