iOS 11 iPhone X模拟器UITabBar图标和标题在顶部覆盖彼此

任何人在UITabBar组件周围的iPhone X模拟器的问题?

我似乎正在渲染的图标和标题在对方之上,我不知道如果我失去了什么,我也跑在iPhone 8模拟器,和一个实际的设备,它看起来很好,就像故事板。

iPhone X:

iPhone X的UITabBar错误

iPhone 8

iPhone 8 UITabBar的作品

我能够解决这个问题,只需在viewDidLayoutSubviews中的UITabBar上调用invalidateIntrinsicContentSize即可。

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

注意:标签栏的底部将需要包含在主视图的底部,而不是安全区域,标签栏应该没有高度限制。

通过使用子类UITabBar来应用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 } } 

UITabBar的高度增加到主页button/行的上方,但在子视图的原始位置绘制并在子视图上覆盖UITabBarItem。

作为一种解决方法,您可以检测到iPhone X,然后将视图的高度缩小32px,以确保标签栏显示在主线上方的安全区域中。

例如,如果您以编程方式创buildTabBarreplace

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

有了这个:

 #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] ; 

注:这可能是一个错误,因为视图大小和标签栏布局是由操作系统设置的。 它可能应该按照iPhone X人机界面指南中的Apple屏幕截图进行显示: https : //developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/

VoidLess提供的答案只是部分修复了TabBar问题。 它修复了tabbar中的布局问题,但是如果你使用隐藏tabbar的viewcontroller,在animation过程中tabbar会被错误地渲染(重现它最好是2有2个segues – 一个模式和一个push,如果你replacesegues,你可以看到tabbar被排除在外)。 看到解决这两个问题的代码。 干得好苹果。

 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 < 90) { size.height += bottomInset } } return size } override var frame: CGRect { get { return super.frame } set { var tmp = newValue if let superview = superview, tmp.maxY != superview.frame.height { tmp.origin.y = superview.frame.height - tmp.height } super.frame = tmp } } } } 

Objective-C代码:

 @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 && (size.height + bottomInset < 90)) { size.height += bottomInset; } } return size; } - (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]; } @end 

当我尝试在自定义TabBarController中设置UITabBar的框架时,我遇到了同样的问题。

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

当我把它调整到新的大小时,问题就消失了

 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); } 

如果您有选项卡栏的任何高度限制,请尝试删除它。

面对同样的问题,解决这个问题。

我今天遇到这个与一个UITabBar手动添加到故事板的视图控制器,当alignment的安全区域的底部常数为0我会得到的问题,但将其更改为1将解决问题。 让UITabBar比正常情况下高出1个像素是我的应用程序可以接受的。

我在这个问题上挠了挠头。 它似乎与tabBar是如何初始化并添加到视图层次结构有关。 我也尝试了上面的解决scheme,如调用invalidateIntrinsicContentSize ,设置框架,以及bottomInsets里面的UITabBar子类。 他们似乎暂时工作,他们打破了一些其他情况或退步标签栏造成一些模糊的布局问题。 当我debugging的问题,我试图分配高度约束的UITabBar和centerYAnchor,但是既不解决问题。 在视图debugging器中,我意识到tabBar高度在问题转载之前和之后是正确的,这导致我认为问题出现在子视图中。 我使用下面的代码来成功解决这个问题,而不会退步任何其他情况。

 - (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]; }]; } } 

假设:我这样做只适用于iPhone X,因为目前似乎没有在任何其他设备上重现。 基于这样的假设,即苹果在未来的iOS版本中不会更改UITabBarButton类的名称。 我们正在UITabBarButton上做这只意味着如果苹果在UITabBar中添加更多的内部子视图,我们可能需要修改代码来调整。

请lemme知道如果这个作品,将开放的build议和改进!

创build一个快速的等价物应该很简单。

我有同样的问题,这是通过设置标签栏布局后的tabBar的项目解决。

在我的情况下,这个问题发生在:

  1. 有一个自定义视图控制器
  2. UITabBar是在视图控制器的初始化程序中创build的
  3. 标签栏项目在视图加载之前设置
  4. 鉴于没有加载标签栏被添加到视图控制器的主视图
  5. 然后,这些项目就像你提到的一样呈现。

我相信你可能会在底部安全布局指南的标签栏。 这可能不是你想要的,因为标签栏似乎做了自己的计算,以安全地将标签栏项目放在iPhone X的主线的顶部。 设置底部约束对超级视图底部 。 您应该看到它在iPhone X以及其他iPhone上正确地布局。

我在启动屏幕故事板上遇到了这个bug,无法通过子类自定义。 经过一番分析,我find了原因 – 我直接使用了UITabBar 。 切换到封装UITabBar解决了这个问题。

注意 – 这可能会被iOS 11.1修复,所以可能不会影响真正的iPhone X应用程序(因为iPhone X很可能会在iOS 11.1上发布)。

我认为这是来自iPhoneX的错误UIKit。 因为它的作品:

 if (@available(iOS 11.0, *)) { if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.top > 0.0) { self.tabBarBottomLayoutConstraint.constant = 1.0; } } 

我在故事板中创build了新的UITabBarController,并将所有视图控制器都推送到了这个新的UITabBarConttoller。 所以,在iPhone X模拟器中一切正常。