I\'m having an issue with my app when testing for iPhone X. I\'m not sure how to adjust this issue, as well as not make it an issue for non iPhone X sizes. This only seems t
After trying a few solutions, what worked for me was adding the following line to viewDidLoad:
[self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
Jonah's and Mehul Thakkar's answers pointed me in the right direction.
Note: I only had a blank tab bar controller in storyboard. The tab bar images and view controllers were setup using the tabBarItem
properties (e.g., tabBarItem.title
on the view controllers).
It's look crazy but I just need to remove this line in my code
self.view.layoutIfNeeded()
I just guess that call layoutIfNeeded on a view that doesn't appear in screen will make this problem happen. Anyway, solution from @mohamed-ali also work correctly. Thanks you so much.
On iOS 12.1 I've solved this issue by overriding safeAreaInsets in the UITabBar subclass:
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
override var safeAreaInsets: UIEdgeInsets {
let insets = super.safeAreaInsets
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
return cachedSafeAreaInsets
}
}
For iOS 13.0 onward,
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
let keyWindow = UIApplication.shared.connectedScenes
.filter { $0.activationState == .foregroundActive }
.compactMap { $0 as? UIWindowScene }
.first?.windows
.filter { $0.isKeyWindow }
.first
override var safeAreaInsets: UIEdgeInsets {
if let insets = keyWindow?.safeAreaInsets {
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
}
return cachedSafeAreaInsets
}
}
Just align the bottom of the UITabBar to the superview, not to the safe area. If you align it to safe area it will be like this:
And when aligned to the superview, it will show correctly:
I think this is because Apple gave the tab bar items a default margin to the bottom if it is on iPhone X as they want the tab bar to be extended to the bottom of the screen to avoid a floating bar.
Add this code in viewDidLoad
DispatchQueue.main.async {
let size = CGSize(width: self.tabBar.frame.width / numberOfTabsFloat,
height: self.tabBar.frame.height)
let image = UIImage.drawTabBarIndicator(color: UIColor.white,
size: size,
onTop: false)
UITabBar.appearance().selectionIndicatorImage = image
self.tabBar.selectionIndicatorImage = image
}
and add this extension
extension UIImage{
//Draws the top indicator by making image with filling color
class func drawTabBarIndicator(color: UIColor, size: CGSize, onTop: Bool) -> UIImage {
let indicatorHeight = size.height
let yPosition = onTop ? 0 : (size.height - indicatorHeight)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: yPosition, width: size.width, height: indicatorHeight))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
"File inspector" from right of Xcode storyboard, enable Safe Area guide layout to support your app in iPhone
This post describes it really well.