如何在iOS 11中正确设置UINavigationBar高度

时间:2017-08-16 11:01:11

标签: ios objective-c uinavigationbar ios11

在我的iOS 9+应用中,我在一些UINavigationBar s“手动”中使用UIViewController(=将它们直接放在VC中,而不是使用UINavigationViewController)。

使用简单的约束为这样的UINavigationBar设置高度之前没有问题。但是在iOS 11中,栏本身仍然正确使用指定的大小,但内容不再正确定位(现在已分配到顶部)。

enter image description here

知道怎么解决这个问题吗?

编辑:

我很确定,这不是“customizing iOS 11 navigation bar height customizing”的重复,这个问题解决了UINavigationBar子类在我直接使用UINavigationBar时遇到的问题。此外,自Beta 4以来所描述的问题似乎已经解决了,而我在Beta 6中遇到了问题。

编辑2:

同时我实现了CharlieSu in the other thread提议的UINavigationBar子类。然而,这并没有解决我的问题。似乎子视图框都已正确设置(无需手动执行),但无论如何都要打破布局。因此手动设置框架没有任何区别。

3 个答案:

答案 0 :(得分:2)

我现在正面临这个问题。 起初,它似乎是酒吧中与我的冲突的另一个高度限制,但我的优先级为1000,所以似乎不是问题。 然后我在UINavigationBar“UINavigationBarContentView”中看到另一个视图,这个视图的高度大于0。

然后我尝试设置navigationBar.clipsToBounds = true并且它有效,因为父视图具有正确的高度......

编辑:如果您需要显示栏的阴影,则需要clipToBounds = false。在这种情况下,您可以继承NavigationBar

import UIKit

class SecondNavigationBar: UINavigationBar {
    override func layoutSubviews() {
        super.layoutSubviews()

        for subview in self.subviews {
            var stringFromClass = NSStringFromClass(subview.classForCoder)
            print("--------- \(stringFromClass)")
            if stringFromClass.contains("BarBackground") {
                subview.frame = self.bounds
            } else if stringFromClass.contains("UINavigationBarContentView") {
                subview.frame = self.bounds
            }
        }
    }
}

答案 1 :(得分:2)

我也遇到过这个问题。我这样解决了:

 -(void)layoutSubviews{
        [super layoutSubviews];
        CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];
        if (rectStatus.size.height==44.f) {

        }else{
            if (@available(iOS 11.0, *)) {
                for ( UIView*aView in self.subviews) {
                    if ([NSStringFromClass(aView.classForCoder) isEqualToString:@"_UINavigationBarContentView"]) {
                        aView.frame = CGRectMake( 0,20,aView.frame.size.width,44);
                    }
                    else if ([NSStringFromClass(aView.classForCoder) isEqualToString:@"_UIBarBackground"]) {
                        aView.frame = CGRectMake(0,0,aView.frame.size.width, 64);
                    }
                }
            }
        }
    }

答案 2 :(得分:0)

在iOS 11中,当你在UIViewController中使用自定义UINavigationBar时,我们可以直接覆盖UINavigationBar的子类中的barPosition(返回UIBarPositionTopAttached而不是默认值UIBarPositionTop) 像这样:

- (UIBarPosition)barPosition {
    return UIBarPositionTopAttached;
}

布局代码如下:

    NSLayoutConstraint* a = [navigationBar.widthAnchor constraintEqualToAnchor:viewController.view.widthAnchor];
    NSLayoutConstraint *b = [navigationBar.centerXAnchor constraintEqualToAnchor:viewController.view.centerXAnchor constant:0];
    NSLayoutConstraint* c = [navigationBar.centerYAnchor constraintEqualToAnchor:viewController.view.topAnchor constant:X];

   [NSLayoutConstraint activateConstraints:@[a,b,c]];   

不要设置它的高度,它应该总是44。

它在iOS 11中运行良好。视图层次结构与UINavigationController相同。
但它不能在iOS 11下运行。我们需要设置UINavigationBarDelegate以返回

中的UIBarPositionTopAttached
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar;