I am trying to place all elements of a navigationBar in the vertical center, but I don't know how to do it?
The gray part above the yellow is the navigationBar. As we can see the title and other elements of the navigationBar are not vertically centered.
How can I do that ?
My Code so far :
let navigationItem = UINavigationItem()
navigationItem.title = sTitle;
navigationBar.frame = CGRectMake(0,0,screenwidth, 50);
navigationBar.titleTextAttributes = [ NSFontAttributeName: titleFont, NSForegroundColorAttributeName: UIColor.blackColor()]
self.view.addSubview(navigationBar);
You can center all your elements ,if you hide the status bar,which can be achieved by add the following to your Info.plist:
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
And your ViewController would look like this:
You can see more ways to hide the status bar in this link :hide Status bar
Firstly try to use native approach to set navigation bar title like:
self.title="Test title"
Or if you would like to have custom font try this :
self.navigationController.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "CustomFont", size: 15)!]
As is mentioned in the comments, the reason these elements are not vertically centered is the fact that the status bar is shown, which reserves 10 points at the top of the navigation bar. It's just not easily visible because it's using the light content style. If your battery was low or charging you'd see the battery at the top right.
You'll need to remove the status bar which will decrease the height of your navigation bar. As there are different ways to hide the status bar based on project setup and context I won't instruct how to remove the status bar, but information on how to do so is widely available.
Once that extra space is removed your items will be vertically centered.
The navbar text/items will never look centered, the way you are displaying things. Technically they are already centered in the Nav bar, but the nav bar manages the centering, and keeps all elements constrained to the lower edge of the nav bar.
The status bar needs 20px. The nav bar should be 44px in height. The top of the nav bar should be constrained to the Top Layout Margin, NOT 0 to the top view boundary itself. The reason for this is that ios removes the status bar (actually the top 20px of whatever displays in portrait mode) when the device is flipped to landscape mode. If your nav bar is 44px, switching the device to landscape mode will show you that the text is correctly centered vertically.
My suggestion for you to see all of this is to create a small view above the nav bar. Make the view 20px high, constrain it to the View.Top (NOT to the margin), and set the background or tintcolor to bright green or something. Then set your nav bar to 44px, constrain it to the Top Layout Margin Guide (NOT to the bottom of the status view you just created, and NOT offset from the View.Top Boundary).
Then when you flip the device back and forth, you'll see that your text is always centered within the nav bar, and the status bar will come and go above the nav bar.
PS. Do this in the storyboard first, it's easiest that way.
Related
I have a UICollectionView that I want to go under the navigation bar. Basically I want it to ignore the entire top safe area, yet still want it to respect the bottom safe area, as there's a tabbar there. This is how it currently looks:
But I want the first cell to start directly the very top of the screen, under the (translucent) navigation bar and the status bar.
If I set collectionView.contentInsetAdjustmentBehavior = .never, then the top part works great, but then the bottom part of the collection view content is hidden by the tabbar - you can't scroll all the way to the bottom so to speak. So I have to manually add a bottom inset again? How do I get the height of the tabbar, including any bottom safe area on devices that have the home bar? Or is there a better way to tell the collectionview to ignore only the top area for its content inset adjustment?
You just need to set the bottom content inset of the collection view manually, after setting the adjustment behavior to .never.
The correct inset (including the tab bar and any home bar) can be found in safeAreaInsets.
collectionView.contentInsetAdjustmentBehavior = .never
collectionView.contentInset.bottom = collectionView.safeAreaInsets.bottom
You'll need to do this at a point when the safeAreaInsets have been set, such as viewDidLayoutSubviews.
As far as I remember, it used to be possible by simply adjusting the edgesForExtendedLayout property of the containing view controller, but that was phased out when safe areas were introduced in iOS 11 I believe.
In my iOS app, I have views rendered beneath the navigation bar. This is because the navigation bar is hidden until the user taps the screen.
The screenshots below illustrate my problem.
The "X" button is rendered beneath the iPhone X's notch and can hardly be seen. This is when I constrain the button's topAnchor to its superview!.topAnchor.
Note that this works as intended for all devices except the iPhone X.
The "X" button in this screenshot is anchored to its superview!.safeAreaLayoutGuide.topAnchor and renders below the navigation bar. This makes sense given Apple's documentation on safeAreaLayoutGuide:
"this guide reflects the portion of the view that is not covered by navigation bars, tab bars, toolbars, and other ancestor views."
However, I want the "X" button to render below the iPhone X's notch and underneath the navigation bar. Here's what it looks like when the navigation bar is hidden:
The "X" button should render right below the notch.
So my question is:
Is there a way to exclude the navigation bar from a view's safeAreaLayoutGuide? And if not, what are my options, other than manually offsetting the button on iPhone X's.
Note that I'm doing everything programmatically. I no longer use Storyboards.
Thanks!
You can change the view controllers safe area insets by adding additional insets.
Create a UIEdgeInsetsMake() object where you subtract the navigation bar height from the top inset. Then add it to the View Controllers additionalSafeAreaInsets.
Declaration: var additionalSafeAreaInsets: UIEdgeInsets { get set }
This is not an answer, but a workaround:
Keep a reference to the "X" button's top constraint.
In layoutSubviews(), update the constant of the top constraint depending on the "X"'s superview and window safeAreaInsets.
override func layoutSubviews() {
// To support devices with a "safe area". If the receiver has a top safe area, position
// the close button beneath the _window's_ safe area.
// Note that using the receiver's safe area does not work in this case because it includes
// the navigation bar. We want to render the close button beneath the navigation bar.
let windowSafeAreaInsets = UIApplication.shared.keyWindow!.safeAreaInsets
// Only use the safe area if the receiver _and_ window have a top safe area. This handles
// the case of non-safe area devices using a hidden navigation bar.
closeButtonTopConstraint.constant = safeAreaInsets.top > 0 && windowSafeAreaInsets != .zero
? windowSafeAreaInsets.top : 16
// Possibly do something similar for landscape and the "X" button's trailing constraint.
}
When I hide my navigation bar I end up with some space under it, it looks like the status bar is twice as big as it should be.
In the image the red line is just touching where the statusbar/navigation bar ends.
My VC is contains a scroll view that is spaced 0 to the edges and spaced 0 to the top layout guide.
Why is the navigation bar not hiding completly? I thought that if you hide the navigation bar you would end up with a 20px statusbar showing only.
I could space my scrollview to be +20 from the top view but that seems a bit hacky.
Look for Extended Edges in attribute inspector of the view controller and uncheck Under Top Bars.
I have a UIViewController. I am designing the screen for iPhone 5s. I have a UIImageView & I am giving top space to container of 20. I also have UINavigationBar at top.So the space given of 20 is not enough. UIImageView is hidden behind the UINavigationBar. I can resolve this issue by giving much space from top. But in that case at design time my UI will not look proper. So is there any way by which space from UINavigationBar is automatically calculated?
In Attribute Inspector set Top Bar to Translucent Navigation Bar like this
then set Top Space of imageView to Top Layout Guide like,
set navigation bar type as opaque Navigation Bar so it will opaque that much space from your view controller and show your view content after navigation bar space they will not hide inside of navigation bar.
but if you set navigation bar type as Translucent Navigation bar then your content will hide inside of navigation bar so set "Opaque Navigation Bar" type. no need to do any other stuff for that.
I hope it will help you!
How can I set the colour of the status bar to be clear. No matter what I do, it is white with some alpha.
I do not want it to disappear and I want the text to be black.
In the picture it might look like nag bar and status bar are grey but actually both are white with some blur affect or nag bar has blur affect and status bar is clear.
Here is what I get despite the clear status bar background colour
The status bar has no background since iOS 7. In other words, it's clear by default.
If you see it white, it means the underlying view is white, and you need to change that.
I was having the same problem. It ended up that my view was constrained to the top layout guide when instead it should have been constrained to the superview. Even though the view is constrained to different points it will look the same in interface builder (in my case, I think this is because I was instantiating the viewcontroller to my navigation controller in code and not displaying the navbar). See the image below.
Click on the constraints for the imageview in the view above and the difference in constraints can be seen in the size inspector.
Constraining to the superview will look like this:
This results in the simulator displaying the view like this:
Notice how the status bar is clear and overlaid on top of the imageview.
Constraining to the top layout guide will look like this:
This results in the simulator displaying the view like this:
Notice how the status bar appears white and how the imageview seems constrained to the status bar (the status bar is white text on a white background fyi).
So, in order to fix this problem, you need to change the constraint of the image view to be constrained to the superview.
You change this by selecting the constraint in this list:
Once you have the constraint selected you can change what the constraint is attached to over here: