Setting NavigationController's NavigationBar translucent property to false causes extra padding - swift

There appears to be extra padding at the top of the root content view when the translucent = false property is set on the NavigationController's NavigationBar (programatically or via the StoryBoard).
I've tried adjusting the scroll view insets but to no avail. translucent = true doesn't cause this problem.
Any ideas why this is happening and what the easiest way to resolve it is?

Ah-ha - got there in the end. When not using a translucent navigation bar you need to ensure that both adjusts scroll view insets and extend edges under opaque bars are set to true on all your view controllers.
Here are the StoryBoard settings:

Related

How to make transparent navigate bar with Table View Cell

I faced with the Table View Cells issue. If I choose default View Controller settings, cells are located under transparent navigation Bar. This is unacceptable because bars items overlap the cell.
navigation bar overload the tableView
If I changing Extend Edges setting at the tab on the right side, specifically "Under Top Bars", cells as expected are located under bar, but in this case NavigateBar is black.
navigation Bar is black
As you see I tried to fix that issue with the Simulated Metrics, but nothing is chanced. Also self.navigationController?.navigationBar.isTranslucent = true and self.navigationController?.view.backgroundColor = .clear in viewDidLoad method did't give any result. I able to color navigation Bar, but i need it transparent. Any ideas?
I guess you haven't set a background color to the ViewController's view. That's why it's appearing black.
Try adding the background color you want and it should work as expected.

NavigationBar Translucent Animation

I have a ViewController which starts with a translucent navigationbar with clear background
navigationBar.isTranslucent = true
navigationBar.barTintColor = .clear
I have scrollView as the first child and scrollView's contentInsetAdjustmentBehavior is set to .never. Now when I scroll the view and scrollView.contentOffset.y > 200 I decided to change the navigationbar as
navigationBar.isTranslucent = false
navigationBar.barTintColor = .someColor
the scroll view get pushed down. I understand that when the view is supposed to be below the navigation bar when it is not translucent. But this makes my scroll effect look ugly. I did little research and found that I can enable Under the top bar option from storyboard, nut unfortunately I am building my using swift, and not using storyboard. I also tried using edgesForExtendedLayout = [.top] but did not work form me.
I wanted was a smooth scrolling behaviour while scrolling, with Navigationbar changing the property of translucent with respect to scrolling contentOffset.

NavigationBar weird extra white space

I'm using a usual view controller with UITableView which is embedded into a navigation controller which is embedded into a tabbar controller:
TabBar Controller
Navigation Controller
UIViewController with TableView
I'm using NavBar with a large title. When I scroll up in a usual way navigation bar with its large title has normal height. But when I touch status bar and tableView scrolls to top, navigation bar gets extra white space between a status bar and its title:
Normal space when scrolling with a finger: https://ibb.co/0BWgB0T
Extra space when touching status bar: https://ibb.co/LxFwDKx
The only thing that helps to avoid that extra space is the following:
edgesForExtendedLayout = UIRectEdge(rawValue: 0)
But it makes tabBar grey, not white as it should be and anyway seems like a quite incorrect solution.
Have anyone faced the same problem?
Ok, suddenly I've found a solution. Yes, it includes this line of code:
edgesForExtendedLayout = UIRectEdge(rawValue: 0)
But also I had to set a tabBar color to preferable and disable its "Translucent" property in Interface Builder.
Hope it'll help someone.

status bar and navigation bar does not display correctly in iPhoneX

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:
1) The status bar is white.
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?
Your UINavigationBar is most likely pinned to the safeAreas of the view. There are several things to consider here:
Current setup
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 Portrait
UIEdgeInsets(top: 0, left: 44, bottom: 21, right: 44) in Landscape
So 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.
Pinning to 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.
Solution
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.
Addendum
A few additional notes on this topic:
We do not need to consider left and right safe areas here. 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.
If you look closely, even the layout in the very last picture is not quite right. The large title is too close to the left edge. To work around this, you would have to tick 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.
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.
isTranslucent is set by default to true. Setting it to false will extend the navigation bar below the status bar.
navigationBar.isTranslucent = false
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.
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".

Gap above ContentView / not the same height as UIScrollview - xib

Issue: gap above where contentView starts. Should be 0.
Despite setting the content view top bottom leading and trailing to 0, the content view has a gap at the top. I am using auto layout only.
Scrollview background is blue &
Content view is grey for easy viewing.
If I set the content view to equal heights as the scroll view, I get an error. And this doesn't seem like the right approach away. According to this setting equal height is optional:
Apple auto layout scrollview page
I do set equal widths.
Entire Screen:
Top of Scroll view:
Bottom of scroll view -> this is right - flush with bottom of scroll view (not sure if that matters)
Constraints:
Subview constraints:
Please help!! Also I am using xib files - not sure if that matters.
Thank you!
You'll notice that the gap is equal in height to the navigation bar.
The gap is there because by default iOS assumes that when using a translucent navigation bar, scroll views (and their subclasses like table views) begin at the top of the screen, behind the translucent navigation bar.
iOS then assumes you do not want your content hidden behind the translucent navigation bar, so it applies a top content inset to any scroll view, of height equal to the navigation bar height.
This behavior can be overridden in two ways:
Unmark Adjust Scroll View Insets on the view controller (see image below)
Make your navigation bar not translucent. If you're using a Storyboard, select the navigation controller that contains the affected view controller, and unmark the Translucent checkbox.