I have a custom UIToolbar
that I'm showing when the tab bar is hidden. The toolbar buttons are too close to the home indicator on iPhone X:
let toolbar = UIToolbar()
let height = tabBarController?.tabBar.frame.height
toolbar.frame = CGRect(x: 0, y: view.bounds.height - height, width: view.bounds.width, height: height)
toolbar.autoresizingMask = [.flexibleWidth, .flexibleTopMargin]
view.addSubview(toolbar)
Buttons are too close to the home indicator
This is what I want it to look like (Mail app) ^
Since this is a custom view, I know that I can change the y position and move it to start at the bottom of safe area but I'd rather move the buttons. I'm using plain UIBarButtonItem
with flexible space in between.
Don’t hide the indicator, add any adornments around it or generally attempt to change its appearance. Same goes for the camera bezel that’s planted at the top of iPhone X. Typically you don’t want to hide the home indicator unless you’ve got a passive viewing experience (i.e. videos, photo slideshow, etc.).
One of the few misses in an otherwise spectacular device. The iPhone X’s screen is amazing but the indicator is only part of the reason why many apps waste space at the top and bottom- Apple’s are the worst offenders. Chrome does a much better job of minimising the title bar than Safari.
If you’ve been around iOS long enough, you’ve likely harnessed container view controllers to better promote abstractions and encapsulation patterns. These contained controllers might find themselves well near the bottom of the screen, and if so — you may want the home indicator to leave you alone.
A simple assignment and a call to setNeedsUpdateOfHomeIndicatorAutoHidden () will perform a slight alpha fade regardless of whether or not its included within an animation block. The last new addition to view controller is a mechanism to inform UIKit if a child view controller should dictate home indicator’s visibility or not.
In iOS 11
, Apple is deprecating the top and bottom layout guides
and being replaced with a single safe area layout guide
.
So use Safe Area Layout Guides
to move the view above from the home indicator.
Using Storyboard :
Storyboard
and in the Interface Builder Document section
Use Safe Area Layout Guides
check box Bottom Constraint
to be relative to the Safe Area
Now the views are aligned above the Home Indicator
.
OR By way of Coding,
toolbar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
toolbar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
toolbar.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
toolbar.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
toolbar.heightAnchor.constraint(equalToConstant: 50)
])
See this article for Positioning Content Relative to the Safe Area
You shouldn't need to set an explicit height or size to get this to work, simply take advantage of the layoutMarginsGuide
and the UIBarPositioningDelegate
protocol, which is adopted by UIToolbarDelegate
.
First, layout your toolbar so that it's pinned to the bottom of the view's layoutMarginsGuide.
let constraints = [
toolbar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
toolbar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
toolbar.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
This will get the toolbar aligned to the safe area on iOS 11+ devices, but you'll need to do one last thing to get the toolbar to extend its background all the way to the bottom of the view. To get that simply conform to UIToolbarDelegate
in your class, set yourself as the toolbar's delegate, implement the function position(for: UIBarPositioning) -> UIBarPosition
, and return the value .bottom
.
The default value for UIToolbar's barPosition is bottom, so this last step may not be necessary in most use cases.
After doing this, you should see your toolbar lay out its items relative to the safe area while extending the background all the way to the bottom of the view, just like you see in Mail and Safari.
The beauty of using layoutMarginsGuide over safeAreaLayoutGuide in this case is that the layoutMarginsGuide insets the layout margins by the safe area by default. Because you don't directly refer to the safe area, your code is backwards compatible all the way to iOS 9 without having to use availability checks.
I ran into this problem also. My solution was to use a generic UIView to account for the bottom safeAreaInset
and then add the toolbar as a subview of that view.
private func addToolbar(_ toolbar: UIToolbar, toView view: UIView) {
toolbar.frame = CGRect(x: 0,
y: 0,
width: view.frame.size.width,
height: 0)
toolbar.sizeToFit() // This sets the standard height for the toolbar.
// Create a view to contain the toolbar:
let toolbarParent = UIView()
toolbarParent.frame = CGRect(x: 0,
y: view.frame.size.height - toolbar.frame.size.height,
width: toolbar.frame.size.width,
height: toolbar.frame.size.height)
// Adjust the position and height of the toolbar's parent view to account for safe area:
if #available(iOS 11, *) {
toolbarParent.frame.origin.y -= view.safeAreaInsets.bottom
toolbarParent.frame.size.height += view.safeAreaInsets.bottom
}
toolbarParent.addSubview(toolbar)
view.addSubview(toolbarParent)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With