IOS 11 iPhone X UITabBar simulator icons and headers displayed on top

Anyone who has issues with the iPhone X simulator around the UITabBar component?

It seems that mine displays the icons and the title on top of each other, I'm not sure I missed something, I also launched it in the iPhone 8 simulator and one of the real devices where it looks great, as shown on the message board.

iPhone X:

iPhone X UITabBar bug

iPhone 8

iPhone 8 UITabBar works

+127
iphone ios11 xcode9-beta uitabbar iphone-x
Sep 14 '17 at 8:59
source share
32 answers
  • one
  • 2

I managed to get around this problem by simply calling invalidateIntrinsicContentSize on the UITabBar in viewDidLayoutSubviews.

-(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self.tabBar invalidateIntrinsicContentSize]; } 

Note. The bottom of the tab bar should be contained in the bottom of the main view, not in the safe area, and the tab bar should not have height restrictions.

+40
Sep 27 '17 at 1:54 on
source share
— -

The answer provided by VoidLess fixes TabBar problems only partially. It fixes problems with the layouts on the tab, but if you use a viewcontroller that hides the tab, the tab does not display correctly during animation (for playback, it is best 2 have 2 segues - one modal and one click. If you alternate segues, you can see the tab which is displayed inappropriately). The code below fixed both issues. Good work apple.

  class SafeAreaFixTabBar: UITabBar { var oldSafeAreaInsets = UIEdgeInsets.zero @available (iOS 11.0, *) override func safeAreaInsetsDidChange() {   super.safeAreaInsetsDidChange()   oldSafeAreaInsets!= safeAreaInsets {       oldSafeAreaInsets = safeAreaInsets      invalidateIntrinsicContentSize()       SuperView?.setNeedsLayout()       SuperView?.layoutSubviews()   } } override func sizeThatFits (_ size: CGSize) - > CGSize {   var size = super.sizeThatFits()    # (iOS 11.0, *) {       let bottomInset = safeAreaInsets.bottom        bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {           size.height + = bottomInset       }   }     }  var frame: CGRect {    {       return super.frame   }    {       var tmp = newValue         superview = superview, tmp.maxY !=       superview.frame.height {           tmp.origin.y = superview.frame.height - tmp.height       }      super.frame = tmp       }   } } > 

Objective-C code:

  @implementation VSTabBarFix {   UIEdgeInsets oldSafeAreaInsets; } - (void) awakeFromNib {   [super awakeFromNib];  oldSafeAreaInsets = UIEdgeInsetsZero; } - (void) safeAreaInsetsDidChange {   [super safeAreaInsetsDidChange];  if (! UIEdgeInsetsEqualToEdgeInsets (oldSafeAreaInsets, self.safeAreaInsets)) {       [self invalidateIntrinsicContentSize];      if (self.superview) {           [self.superview setNeedsLayout];           [self.superview layoutSubviews];       }   } } - (CGSize) sizeThatFits: (CGSize) size {   size = [super sizeThatFits: size];  if (@available (iOS 11.0, *)) {       float bottomInset = self.safeAreaInsets.bottom;       if (bottomInset > 0 && size.height < 50 && & && & & > ( +   < 90)) {           size.height + = bottomInset;       }   }   ; } - (void) setFrame: (CGRect) frame {   if (self.superview) {       if (frame.origin.y + frame.size.height!= self.superview.frame.size.height) {           frame.origin.y = self.superview.frame.size.height - frame.size.height;       }   }   [super setFrame: frame]; } @ > 
+23
Nov 10 '17 at 14:57
source share

There is a trick by which we can solve the problem.

Just enter the UITabBar in the UIView.

It really works for me.

Or you can follow this Link for more details.

+21
Nov 24 '17 at 11:11
source share

override UITabBar sizeThatFits(_) for safeArea

 extension UITabBar { static let height: CGFloat = 49.0 override open func sizeThatFits(_ size: CGSize) -> CGSize { guard let window = UIApplication.shared.keyWindow else { return super.sizeThatFits(size) } var sizeThatFits = super.sizeThatFits(size) if #available(iOS 11.0, *) { sizeThatFits.height = UITabBar.height + window.safeAreaInsets.bottom } else { sizeThatFits.height = UITabBar.height } return sizeThatFits } } 
+13
May 15 '18 at 8:52
source share

I added this to the viewWillAppear my custom UITabBarController , because none of the answers provided worked for me:

 tabBar.invalidateIntrinsicContentSize() tabBar.superview?.setNeedsLayout() tabBar.superview?.layoutSubviews() 
+9
May 08 '18 at 12:02
source share

Moving the tab bar 1 point from the bottom worked for me.

Of course, you will get a space by making it so that you will need to fill it out somehow, but the text / icons are now correctly positioned.

+7
Dec 06 '17 at 20:53 on
source share

I have the same problem.

enter image description here

If I set any non-zero constant in the lower UITabBar constraint to a safe area:

enter image description here

He begins to work as expected ...

enter image description here

This is the only change I made, and I have no idea why this works, but if anyone does, I would like to know.

+7
Dec 14 '17 at 19:51 on
source share

Fixed using a subclass of UITabBar to use safeAreaInsets:

 class SafeAreaFixTabBar: UITabBar { var oldSafeAreaInsets = UIEdgeInsets.zero @available(iOS 11.0, *) override func safeAreaInsetsDidChange() { super.safeAreaInsetsDidChange() if oldSafeAreaInsets != safeAreaInsets { oldSafeAreaInsets = safeAreaInsets invalidateIntrinsicContentSize() superview?.setNeedsLayout() superview?.layoutSubviews() } } override func sizeThatFits(_ size: CGSize) -> CGSize { var size = super.sizeThatFits(size) if #available(iOS 11.0, *) { let bottomInset = safeAreaInsets.bottom if bottomInset > 0 && size.height < 50 { size.height += bottomInset } } return size } } 
+5
Sep 29 '17 at 10:33 on
source share

Yeah! This is actually magic!

I finally figured it out after hours of cursing Apple.

UIKit really handles this for you, and it seems that the offset elements of the tab bar are due to incorrect settings (and possibly due to a real UIKit error). No need to subclass or in the background.

UITabBar will “just work” if it is limited to the bottom of the superview, NOT the bottom safe area .

It even works in Interface Builder.

Correct setup

Working in IB

  1. In the interface designer, when viewing as an iPhone X, drag the UITabBar to where it is attached to the bottom tab of the safe area. When you drop it, it should look right (fill the space to the very bottom).
  2. Then you can do “Add Missing Constraints” and IB will add the correct constraints and your tab bar will magically work on all iPhones! (Note that the lower limit looks as if it has a constant value equal to the height of the unsafe area of ​​the iPhone X, but in fact this constant is 0)



Sometimes it still doesn't work

Broken in ib

What is really stupid is that you can see the error in IB, even if you add the exact restrictions that IB adds in the steps above!

  1. Drag the UITabBar and do not snap it to the bottom liner of the safe area
  2. Add lead, end, and lower constraints to the superview (insecure area). Oddly enough, this will fix it if you do "Invert the first and second element" in the constraint inspector for the lower constraint. _ (ツ) _ / ¯
+5
Jun 10 '18 at 6:41
source share

Solved for me by calling [tabController.view setNeedsLayout]; after rejecting the modality in the completion block.

 [vc dismissViewControllerAnimated:YES completion:^(){ UITabBarController* tabController = [UIApplication sharedApplication].delegate.window.rootViewController; [tabController.view setNeedsLayout]; }]; 
+4
Apr 04 '18 at 19:50
source share

UITabBar increases in height to be higher than the home button / line, but draw a subview at its original location and overlay the UITabBarItem on the subview.

As a workaround, you can spot the iPhone X and then reduce the size of the view by 32px to make sure the tab bar appears in a safe area above the home line.

For example, if you create a TabBar, programmatically replace

 self.tabBarController = [[UITabBarController alloc] init]; self.window.rootViewController = self.tabBarController; 

Wherein:

 #define IS_IPHONEX (([[UIScreen mainScreen] bounds].size.height-812)?NO:YES) self.tabBarController = [[UITabBarController alloc] init]; self.window.rootViewController = [[UIViewController alloc] init] ; if(IS_IPHONEX) self.window.rootViewController.view.frame = CGRectMake(self.window.rootViewController.view.frame.origin.x, self.window.rootViewController.view.frame.origin.y, self.window.rootViewController.view.frame.size.width, self.window.rootViewController.view.frame.size.height + 32) ; [self.window.rootViewController.view addSubview:self.tabBarController.view]; self.tabBarController.tabBar.barTintColor = [UIColor colorWithWhite:0.98 alpha:1.0] ; self.window.rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1.0] ; 

NOTE. This can be a mistake, since the dimensions of the view and the layout of the tab bar are set by the OS. It should probably display according to the Apple image in the iPhone X Human Interface Guide: https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/

+2
Sep 14 '17 at 9:50
source share

In my case, I set the custom height of UITabBar to UITabBarController, for example:

  override func viewWillLayoutSubviews() { var tabFrame = tabBar.frame tabFrame.size.height = 60 tabFrame.origin.y = self.view.frame.size.height - 60 tabBar.frame = tabFrame } 

Removing this code was the solution to correctly display TabBar on iPhone X.

+2
Feb 08 '18 at 13:45
source share

I had the same problem when I tried to set the UITabBar frame to my custom TabBarController.

 self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight); 

When I just set it to a new size, the problem disappeared.

 if(IS_IPHONE_X){ self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kPhoneXTabBarHeight, self.view.frame.size.width, kPhoneXTabBarHeight); } else{ self.tabBar.frame = CGRectMake(0, self.view.frame.size.height - kTabBarHeight, self.view.frame.size.width, kTabBarHeight); } 
+1
Sep 14 '17 at 23:27
source share

Today I came across a UITabBar manually added to the view controller in the storyboard, when aligned to the bottom of the safe area with constant 0, I would get the problem, but changing it to 1 would fix the problem. Having a UITabBar 1 pixel larger than usual is acceptable for my application.

+1
Sep 28 '17 at 9:39 on
source share

I scratched my head over this problem. This seems to be related to how the tabBar is initialized and added to view the hierarchy. I also tried solutions like calling invalidateIntrinsicContentSize , setting a frame, and also bottomInsets inside a subclass of UITabBar. They seem to work, but temporarily, and they break some other script or regress the tab bar, causing some ambiguous layout problem. When I debugged the problem, I tried to assign height limits to UITabBar and centerYAnchor, however, no problem was fixed. I realized that the tabBar height was correct before and after reproducing the problem, which made me think that the problem was in the subtitles. I used the code below to successfully solve this problem without regressing any other scenario.

 - (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; if (DEVICE_IS_IPHONEX()) { [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) { for (UIView *view in self.tabBar.subviews) { if ([NSStringFromClass(view.class) containsString:@"UITabBarButton"]) { if (@available (iOS 11, *)) { [view.bottomAnchor constraintEqualToAnchor:view.superview.safeAreaLayoutGuide.bottomAnchor].active = YES; } } } } completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) { [self.tabBar layoutSubviews]; }]; } } 

Assumptions: I only do this for the iPhone X, as it is not currently playing on any other device. Based on the assumption that Apple will not change the class name UITabBarButton in future releases of iOS. We do this on UITabBarButton only when it means that if apples add more internal routines to UITabBar, we may need to change the code to adapt to this.

Please let me know if this works, suggestions and improvements will be open!

To do this, it should be easy to create a quick equivalent.

+1
Nov 16 '17 at 1:21
source share

From this lesson:

https://github.com/eggswift/ESTabBarController

and after initializing the tab bar writing this line to the appdelegate class

 (self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator 

Solves my problem with the tab bar.

Hope it solves your problem.

thank

+1
Dec 11 '17 at 13:55 on
source share

Select the tab and select the "Save relative field fields" check box in the inspector editor as follows:

enter image description here

+1
Jan 05 '18 at 15:37
source share

If you have a height limit for the tab bar, try deleting it.

Faced the same problem, and fixing it solved the problem.

0
Sep 25 '17 at 12:13
source share

I created a new UITabBarController in my storyboard and clicked all view controllers on this new UITabBarConttoller. So, everything works well in the iPhone X simulator.

0
Oct. 25 '17 at 9:33
source share

For iPhone, you can do this by subclassing UITabBarController.

 class MyTabBarController: UITabBarController { override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if #available(iOS 11, *) { self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true self.tabBar.invalidateIntrinsicContentSize() } } } 

Open the storyboard and enable the Use Safe Area Planning Guide and change the UITabbarController class to MyTabBarController

PS This solution is not tested in the case of a universal application and iPad.

0
Dec 19 '17 at 7:39 on
source share

try changing the screensaver with the size @ 3x (3726 × 6624)

0
Jan 21 '18 at 17:05
source share

For me, remove the [self.tabBar setBackgroundImage:] work, maybe this is a UIKit error

0
Jan 25 '18 at 6:21
source share

For me, this fixed all the problems:

  override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let currentHeight = tabBar.frame.height tabBar.frame = CGRect(x: 0, y: view.frame.size.height - currentHeight, width: view.frame.size.width, height: currentHeight) } 
0
Feb 07
source share

I had a similar problem, at first it displayed correctly, but after setting badgeValue on one of the tabBarItem, it broke the layout. That it worked for me without a subclass of UITabBar was like that on my already created subclass of UITabBarController .

 -(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; NSLayoutYAxisAnchor *tabBarBottomAnchor = self.tabBar.bottomAnchor; NSLayoutYAxisAnchor *tabBarSuperviewBottomAnchor = self.tabBar.superview.bottomAnchor; [tabBarBottomAnchor constraintEqualToAnchor:tabBarSuperviewBottomAnchor].active = YES; [self.view layoutIfNeeded]; } 

I used superview tabBar to make sure that the constraints / anchors are in the same hierarchy of views, and to avoid failures.

Based on my understanding, since this seems to be a UIKit error, we just need to rewrite / re-set the limitations of the tab bar so that the automatic placement mechanism can correctly position the tab bar again.

0
Sep 13 '18 at 4:49
source share

The simplest solution I found was to simply add a 0.2 pt space between the bottom of the tab bar and the bottom of safeAreaLayoutGuide.bottomAnchor, as shown below.

 tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -0.2) 
0
Sep 27 '18 at
source share
 open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) } 

This worked for me, creating an extension on the UITabBarController

0
Dec 10 '18 at 6:22
source share

I used the UITabBarController in the storyboard, and at first it worked fine for me, but after upgrading to the new version of Xcode, it began to cause me problems with the height of the tabBar.

For me, the fix was to remove the existing UITabBarController from the storyboard and recreate it by dragging it from the library of objects of the interface designer.

0
Aug 13 '19 at 7:42
source share

I had the same problem that was solved by setting tabBar elements after the tab bar was laid out.

In my case, the problem occurred when:

  • There is a custom view controller
  • UITabBar is created in the controller initializer of the form
  • Tab bar items are set before loading the view.
  • As a result, the tab bar loaded into the main view controller view was loaded.
  • Then the items are displayed as you mention.
-one
Sep 14 '17 at 20:49
source share

I think this is a UIKit error from iPhoneX. because it works:

 if (@available(iOS 11.0, *)) { if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.top > 0.0) { self.tabBarBottomLayoutConstraint.constant = 1.0; } } 
-one
Sep 25 '17 at 17:40
source share

I believe that you could lay out a tab bar against the bottom safe layout guide. This is probably not what you need, as the tab bar seems to do its own calculations to safely position tab bar items on top of the home bar in iPhone X. iPhone X , as well as on other iPhones.

-one
Oct 09 '17 at 0:17
source share
  • one
  • 2



All Articles