iOS 11 - UINavigationItem titleView when using Large Titles mode
I can't find any documentation on this, so I played a bit. It seems in iOS 11, you won't be able to get that title to be a button and display large at the left.
I don't know if this is a bug or the expected result, as it seems to be a new feature. The latest (iOS 11) Human Interface Guidelines (HIG) discuss the larger title label as being a way to give the user clear context. The HIG also discuss space between buttons. However, there's no discussion of using a button as the title.
To recreate, I set up a Single View project. I embedded the view controller in a navigation controller.
In ViewController.swift
's viewDidLoad
, I added this code:
let titleButton = UIButton(type: .roundedRect)
titleButton.setTitle("Hello Button!", for: UIControlState.normal)
let navController = parent as! UINavigationController
navController.navigationBar.topItem!.title = "Hello???"
navController.navigationBar.topItem!.titleView = titleButton
navController.navigationBar.prefersLargeTitles = true
This ends up looking something like your example.
IF I:
set
.title
to empty string, or remark the line out: navbar is stretched, and no title text shows (or title text set in Interface Builder shows)remark out
.prefersLargeTitles
, or set it tofalse
: the navbar is the normal height, the button displays, but no title text displays.remark out the
titleView
line, AND:- leave the
.prefersLargeTitles
set totrue
: thetitle
text displays large at the left, and the navbar's height is stretched. - set the
.prefersLargeTitles
tofalse
: thetitle
text displays in the top center, and the navbar is normal height.
- leave the
Update: link to sample project on GitHub
I was able to replace the navigation bar big title with a custom view by using a subclass of UINavigationBar
and manually changing the view hierarchy :
@interface MYNavigationBar : UINavigationBar
@end
@implementation MYNavigationBar
// ...
- (void)layoutIfNeeded
{
[self setupTitle];
[super layoutIfNeeded];
}
- (void)setupTitle
{
// UINavigationBar
// -> ...
// -> _UINavigationBarLargeTitleView
// -> UILabel << Big Title Label
// -> UIView
// -> UILabel << Big Title Label animating from back button during transitions
for (UIView *view in self.subviews) {
NSString *className = NSStringFromClass(view.classForCoder);
if ([className containsString:@"LargeTitleView"]) {
for (UIView *view2 in view.subviews) {
if ([view2 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view2];
}
for (UIView *view3 in view2.subviews) {
if ([view3 isKindOfClass:[UILabel class]]) {
[self convertLabel:(UILabel *)view3];
}
}
}
}
}
}
- (void)convertLabel:(UILabel*)label
{
// I kept the original label in the hierarchy (with the background color as text color)
// and added my custom view as a subview.
// This allow the transformations applied to the original label to be also applied to mine.
}
Please note that Apple might reject your app because of this trick.