I am trying to implement a custom Navigation Title on an iOS app.
The StoryBoard looks like this:
The place that I want to have the custom Navigation Title is the last view ( the message view ), and because I use an image and text this means that I need to have custom width and height. By needing this if I do in viewDidLoad
:
let rect = CGRect(x: 0, y:0, width: 150, height: 88)
titleView = UIView(frame: rect)
......
titleView?.addSubview(imageView)
......
titleView?.addSubview(label)
navigationItem.titleView = titleView
The height of the title is blocked to 44pt.
But how I managed to do it is adding the subViews to the navigation bar:
var navigationBar: MessagesNavigationBar? {
guard let navigationBar = navigationController?.navigationBar as? MessagesNavigationBar else {
return nil
}
return navigationBar
}
And in viewDidLoad
let rect = CGRect(x: 0, y:0, width: 150, height: 88)
titleView = UIView(frame: rect)
......
titleView?.addSubview(imageView)
......
titleView?.addSubview(label)
navigationBar?.addSubview(titleView!)
But the problem is that I have to remove the subviews when I leave the view, otherwise whatever I add there will be present in the table view as well.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if navigationBar != nil {
titleView?.removeFromSuperview()
}
}
Which kinda makes me feel that I'm not doing the right thing and I find difficult to add a fade out animation to those subViews when I leave the conversation. (i.e. native messages app on iOS).
So what is the right way of creating a custom Title Navigation Bar in iOS 12?
Scenes
Creating your custom titleView
and assigning it to navigationItem.titleView
is what you want. On older systems (pre iOS 11) you just might need to call sizeToFit()
on the titleView
.
This way you can create this titleView
Swift
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView()
NSLayoutConstraint.activate([
imageView.heightAnchor.constraint(equalToConstant: 20),
imageView.widthAnchor.constraint(equalToConstant: 20)
])
imageView.backgroundColor = .red
let titleLabel = UILabel()
titleLabel.text = "Custom title"
let hStack = UIStackView(arrangedSubviews: [imageView, titleLabel])
hStack.spacing = 5
hStack.alignment = .center
navigationItem.titleView = hStack
}
Obj-C
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc] init];
[NSLayoutConstraint activateConstraints:@[
[imageView.heightAnchor constraintEqualToConstant:20],
[imageView.widthAnchor constraintEqualToConstant:20]
]];
imageView.backgroundColor = [UIColor redColor];
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.text = @"Custom title";
UIStackView *hStack = [[UIStackView alloc] initWithArrangedSubviews:@[imageView, titleLabel]];
hStack.spacing = 5;
hStack.alignment = UIStackViewAlignmentCenter;
self.navigationItem.titleView = hStack;
}
You might also need to have the right set of autolayout constraints or use UIStackView
.