How to correctly set UINavigationBar height in iOS 11

核能气质少年 提交于 2019-12-03 16:29:34

I'm facing this problem right now. At first, It appears to be another height constraint in the bar that conflicts with mine, but mine has 1000 priority so it seems not to be the problem. Then I see another view inside UINavigationBar "UINavigationBarContentView", this view has height bigger than 0.

I then tried to set navigationBar.clipsToBounds = true and it works, cause parent view has the correct height...

EDIT: If you need to show the shadow of the bar, you will need clipToBounds = false. In that case you can subclass the 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
            }
        }
    }
}

I've had this problem, too. I solved it this way:

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

In iOS 11, we can directly override barPosition in subclass of UINavigationBar (return UIBarPositionTopAttached instead default value UIBarPositionTop ) when u use custom UINavigationBar in UIViewController
like this :

- (UIBarPosition)barPosition {
    return UIBarPositionTopAttached;
}

the layout code will be like this:

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

Don't set it's height ,it should always be 44.

It's works well in iOS 11. The view hierarchy is as same as UINavigationController's.
But it doesn't work below iOS 11. We need set the UINavigationBarDelegate to return UIBarPositionTopAttached in

- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar;  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!