问题
In my iOS 9+ app I use UINavigationBar
in some of the UIViewController
s "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