How to correctly set UINavigationBar height in iOS 11

和自甴很熟 提交于 2020-01-12 09:19:11

问题


In my iOS 9+ app I use UINavigationBar in some of the UIViewControllers "manually" (= placing them directly in the VC instead of using UINavigationViewController).

Setting a height for such a UINavigationBar using a simple contraint was no problem before. However in iOS 11 the bar itself still correctly uses the assigned size, but the content is not positioned correctly any more (is now alligned to the top).

Any idea how to solve this?

EDIT:

I am pretty sure, that this is not a duplicate of "customizing iOS 11 navigation bar height customizing", this this question addresses a problem with UINavigationBar subclasses while I directly use UINavigationBar. Additionally the described problem seems to solved since Beta 4, while I am experiencing the problem in Beta 6.

EDIT 2:

Meanwhile I implemented a UINavigationBar subclass as proposed by CharlieSu in the other thread. However this did not solve the problem in my case. It seems that the subview frame are all set properly (without doing this manually), but the layout is broken anyway. So setting the frames manually does not make any difference.


回答1:


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



回答2:


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



回答3:


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;  


来源:https://stackoverflow.com/questions/45711765/how-to-correctly-set-uinavigationbar-height-in-ios-11

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