Custom UINavigationBar's title mis-placed on rotation to landscape of some devices.

Greetings,

Have various menus which have a tall custom navigation bar (about 100 points in height). Right below the title, we place a segmented control. Works perfectly on all 8.x devices.


However on some iOS 9.x devices upon rotation to landscape the title "drops" to the baseline of the navigation bar. Same thing occurs to the back button indicator. Rotating back to portrait corrects the issue temporarily.


The iOS 9 devices on which it fails are:

  1. iPhone 4/4s
  2. iPhone 5/5s
  3. iPhone 6/6s


Removed the segmented control and all other UI controls except the title and it still happens. In the custom navigation bar's layoutSubviews, the following code is executed:

    CGFloat dy = self.frame.size.height - 44.0f;
    [self setTitleVerticalPositionAdjustment:-dy forBarMetrics:UIBarMetricsDefault];


Any suggestions?

Bug Report # 22739329

Has anyone noticed how on an iPhone 6 and 6 Plus in landscape the Bookmarks menu in Safari switches the position of the segmented control from being below the navigation bar's title and backbutton to being above them ? Is this related to the issue I'm experiencing?

Also the separator line between the navigation bar and the table view below it disappears when in landscape. Given that the line is a pixel in height, I doubt it was a space saving measure, probably a bug.

UINavigationBar really doesn't do well when you change its geometry. Much of its layout expects it to be at its normal sizes (44 or 32pts tall). Effectively what you have is an undefined behavior.

So the sample code at https://developer.apple.com/library/ios/samplecode/NavBar/Introduction/Intro.html specifically CustomNavigationBar.m lines 14-30 is not supported? This code is from 2015 and also subclasses a navigation bar and changes the height to make it taller. I must admit, I'm now totally confused.

@implementation CustomNavigationBar

- (CGSize)sizeThatFits:(CGSize)size
{
    CGSize navigationBarSize = [super sizeThatFits:size];

    //Pad the base navigation bar height by the fitting height of our button.
    CGSize buttonSize = [self.customButton sizeThatFits:CGSizeMake(size.width, 0)];
    navigationBarSize.height += buttonSize.height;

    return navigationBarSize;
}

I was not aware of this sample unfortunately, but it is basically not sufficient for your purposes, and there isn't API available that would allow for you to do what you want. Basically, UINavigationBar doesn't provide the means to subclass it effectively in many circumstanes, and this sample code should not have been published.

Rincewind,

thank you for your candid response. Sometimes all that developers have to go on is sample code from Apple. Glad that you took a stand about that sample code.

I do think however in the long run UINavigationBar should be made more flexible so that it can be subclassed and have its geometry changed using a public API , specifically its height.


There's a need among developers to be able to make the nav bar taller, as demonstrated by simply doing a web search for "customize UINavigationBar"


Until then you may want to hide the UINavigationController's public initWithNavigationBarClass:toolbarClass method since that encourages subclassing of UINavigationBar and perhaps the UIToolbar class as well.



Note: After experimenting a bit more with a standard height UINavigationBar, I observed that there appears to be a bug with setTitleVerticalPositionAdjustment:forBarMetrics: where the vertical position adjustment is not respected on iPhones 6 and below. If the vertical position adjustment is set to for example to -24 then upon rotation to landscape the vertical position adjustment is dropped as if set to something else. Unless the method setTitleVerticalPositionAdjustment:forBarMetrics: falls in the category of unsupported public APIs then perhaps that warrants a fix?

And again this is observable in a standard height navigation bar.


Thanks again!


Neal

Rincewind,

I see what the issue is. On an iPhone rotation to landscape (compact height), the UINavigationBar may become the compact height version and shrinks from 44 to 32 points tall. At this point you recenter the title (and other UIBarButtonItems if present) in the Y direction, and the effective vertical position adjustment becomes 0. If someone throws in modifying the height of the UInavigationBar, the title is still centered as if the UINavigationBar was still 32 points tall.


In the future, you may want to deprecate the setTitleVerticalPositionAdjustment:forBarMetrics: since it really doesn't work too well in that environment.


Thanks

Custom UINavigationBar's title mis-placed on rotation to landscape of some devices.
 
 
Q