iOS 11 iPhone X模拟器UITabBar图标和标题正在渲染顶部覆盖海誓山盟
任何人在UITabBar组件周围的iPhone X模拟器有问题吗?我似乎正在渲染图标和标题在彼此之上,我不确定是否我错过了任何东西,我也在iPhone 8模拟器中运行它,以及它看起来不错的一个实际设备如故事板上所示。iOS 11 iPhone X模拟器UITabBar图标和标题正在渲染顶部覆盖海誓山盟
iPhone X:
iPhone 8
的UITabBar在高度上增加是主页按钮/线之上,但是绘制子视图在其原始位置并在子视图上覆盖UITabBarItem。
作为解决方法,您可以检测iPhone X,然后将视图高度缩小32px,以确保标签栏显示在主线上方的安全区域中。
例如,如果您建立的TabBar编程更换
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] ;
注意:这可能是一个错误,作为视图大小和标签栏布局由OS设置。它应该按照iPhone X人机界面指南中的Apple屏幕截图显示:https://developer.apple.com/ios/human-interface-guidelines/overview/iphone-x/
不固定我看到,我没有编程创建Tab栏,我用故事板构建它的约束被设置为屏幕的底部。对我来说,我们感到很奇怪,我们必须检测它是否是iPhone X,然后对布局进行一些调整,而它们只是通过它自身将TabBar的高度向上调整,而无需更改任何代码。 –
这种感觉对我来说更像是一个bug,我想我会对此做一个错误报告,看看它出了什么问题。谢谢你的帮助!! –
使用主屏幕边界的确切高度来确定应用程序是否在iPhone X上运行真的不是一个好主意。如果明年的模型是相同的点大小,会发生什么情况?或者,如果应用程序在横向模式下运行? – roperklacks
我遇到了同样的问题,这是通过在标签栏布局后设置tabBar项来解决的。
在我的情况下,问题发生时:
- 有一个自定义视图控制器
- 中的UITabBar一样在视图控制器的初始化创建
- 鉴于之前做过的标签栏项目设置加载
- 在视图中加载的标签栏被添加到视图控制器的主视图中
- 然后,按照您提到的方式呈现项目。
我在尝试在自定义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);
}
'kPhoneXTabBarHeight'的值是什么? –
我刚刚添加了32点到kTabBarHeight(这是45)的以前的值。但是您不必指定完全相同的值,对于我来说,它也可以正常工作,而无需指定tabBar的框架。但是,如果您确实指定了它,则必须调整iPhone X上的其他高度。 – Evgeny
完全破解,但它是这些解决方案中唯一适合我的解决方案。 –
如果您对标签栏尝试删除任何高度约束。
面对同样的问题,并解决这个问题。
我认为这是来自iPhoneX的一个bug UIKit。 ,因为它的工作原理:
if (@available(iOS 11.0, *)) {
if ([UIApplication sharedApplication].keyWindow.safeAreaInsets.top > 0.0) {
self.tabBarBottomLayoutConstraint.constant = 1.0;
}
}
你可以给tabBarBottomLayoutConstraint是什么更多信息? – user3099837
是的,tabBarBottomLayoutConstraint是什么? –
我能够通过简单地在UITabBar中viewDidLayoutSubviews呼吁invalidateIntrinsicContentSize来解决这个问题。
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self.tabBar invalidateIntrinsicContentSize];
}
注:标签栏的底部将需要包含到主视图的底部,而不是安全区,并在标签栏应该没有高度约束。
我今天遇到了这个问题,用一个UITabBar手动添加到故事板中的视图控制器,当用常数0对齐安全区域的底部时,我会得到问题,但将其更改为1会解决问题。使UITabBar比正常情况下高出1个像素是我的应用程序可以接受的。
没有为我工作。我正在使用手动添加的UITabBar。 –
不理想,但似乎为我工作 – Vad
固定用的子类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
}
}
解决部分问题,但不是全部。请参阅下面的完整答案 –
我相信你可能会铺设了对底部安全布局引导标签栏。这可能不是你想要的,因为标签栏似乎做了自己的计算,将标签栏项目安全地放置在iPhone X的主线上。Setup your bottom constraint against the superview bottom。您应该看到它在iPhone X以及其他iPhone上正确布局。
我在启动屏幕故事板上遇到了这个bug,无法通过子类自定义。经过一些分析,我设法找出原因 - 我直接使用UITabBar
。切换到封装了UITabBar
的UITabBarController
解决了该问题。
注 - 这可能会由iOS 11.1修复,因此可能不会影响真正的iPhone X应用程序(因为iPhone X很可能会在iOS 11.1上发布)。
我在故事板中创建了新的UITabBarController,并将所有视图控制器推送到了这个新的UITabBarConttoller。所以,在iPhone X模拟器中一切运行良好。
这也为我解决了它。 Xcode 9 IB生成解决问题的UITabBarController的XML的方式有些不同。 – Tiago
由VoidLess提供的答案只修复了TabBar问题的一部分。它修复了tabbar中的布局问题,但是如果你使用viewcontroller来隐藏tabbar,在动画过程中tabbar被错误地渲染(重现它最好是2有2个segues - 一个模式和一个push。如果你改变了segues,你可以看到不合适的标签栏)。下面的代码解决了这两个问题。干得好苹果。
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
我已经划伤我的头了这个问题。它似乎与tabBar如何初始化并添加到视图层次结构有关。我也尝试了上面的解决方案,如调用invalidateIntrinsicContentSize
,设置框架,以及在UITabBar子类中的bottomInsets
。他们似乎暂时工作,他们打破了一些其他情况或通过引起一些模糊的布局问题来回归标签栏。当我调试这个问题时,我尝试将高度约束分配给UITabBar和centerYAnchor,但是没有解决问题。我在视图调试器中意识到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这样做,因为它似乎并没有重现,此刻任何其他设备上。 基于Apple未在未来的iOS版本中更改UITabBarButton类的名称这一假设。 我们只在UITabBarButton上这样做时,意味着如果苹果在UITabBar中添加更多内部子视图,我们可能需要修改代码以进行调整。
请lemme知道这是否有效,将开放的建议和改进!
为此创建一个快速的等价物应该很简单。
我把它放在''viewDidAppear(animated:)''我的'UITabBarController'中,它工作正常。谢谢! –
什么参数你通过大小和协调员?从视图didAppear – sulabh
移动标签栏距离底部 1分为我工作。
当然,你会得到一个缺口,你必须以某种方式填写,但文本/图标现在正确定位。
从本教程:
https://github.com/eggswift/ESTabBarController
和标签栏在AppDelegate类
(self.tabBarController.tabBar as? ESTabBar)?.itemCustomPositioning = .fillIncludeSeparator
解决了我的标签栏的问题写这行的初始化后。
希望其解决您的问题
感谢
对于iPhone,你可以做到这一点,子类UITabBarController。
class MyTabBarController: UITabBarController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
self.tabBar.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.tabBar.invalidateIntrinsicContentSize()
}
}
}
转到故事板,并允许使用安全区域布局指南和变化类的的UITabBarController到MyTabBarController
P.S该解决方案是不是在普及应用和iPad的情况下进行测试。
对于我删除[self.tabBar setBackgroundImage:]
工作,也许这是错误的UIKit
对我来说,这个固定的所有问题:
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)
}
我的情况是,我已经设置在我的UITabBarController自定义UITabBar高度,就像这样:
override func viewWillLayoutSubviews() {
var tabFrame = tabBar.frame
tabFrame.size.height = 60
tabFrame.origin.y = self.view.frame.size.height - 60
tabBar.frame = tabFrame
}
删除此代码是为的TabBar在iPhone上X.正确显示
我类似的问题的解决:选择指标图像视图下沉在iPhone X的约16个点在tabBar视图。 – Itachi
仅供参考 - 这不幸在Xcode 9.2beta – tdios