Make Navigationbar's Titleview Larger Than Itself

Make NavigationBar's titleView larger than itself

I found why you got this issue. It's because of a private view which has name _UINavigationBarContentView. It's a subview of UINavigationBar. navigationItem.titleView is contained in this view.

Sample Image

At first time, when you change navigationItem.titleView. _UINavigationBarContentView.clipsToBounds is false .But after you push another controller and pop back, _UINavigationBarContentView.clipsToBounds is true. That's why titleView is cropped.

So i have a temporary solution. Each time when viewController appears, find this view and change _UINavigationBarContentView.clipsToBounds to false and layout titleView.

override func viewDidAppear(_ animated: Bool) {
for view : UIView in (navigationController?.navigationBar.subviews)! {
view.clipsToBounds = false;
}
navigationItem.titleView?.layoutIfNeeded()
}

override func viewWillAppear(_ animated: Bool) {
for view : UIView in (navigationController?.navigationBar.subviews)! {
view.clipsToBounds = false;
}
navigationItem.titleView?.layoutIfNeeded()
}

I tried and it works. But i think you shouldn't do something whit it because it's private view. Maybe Apple don't want us do anything with it.

Hope somehow my suggestion can help you. Good luck ;)

SOLUTION

Adding observer for _UINavigationBarContentView.clipsToBounds, each time when it changes to false, set to true and update layout of titleView

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

let logo = UIImage(named: "Logo")
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
let imageView = UIImageView(image: logo)
imageView.frame = CGRect(x: 0, y: 0, width: titleView.frame.width, height: titleView.frame.height)
titleView.addSubview(imageView)
imageView.contentMode = .scaleAspectFit
imageView.image = logo
navigationItem.titleView = titleView
navigationController?.navigationBar.subviews[2].addObserver(self, forKeyPath: "clipsToBounds", options: [.old, .new], context: nil)
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if (navigationController?.navigationBar.subviews[2].isEqual(object))! {
DispatchQueue.main.async {
self.navigationController?.navigationBar.subviews[2].clipsToBounds = false
self.navigationItem.titleView?.layoutIfNeeded()
}
}
}

deinit {
navigationController?.navigationBar.subviews[2].removeObserver(self, forKeyPath: "clipsToBounds")
}

For more detail and easier, you can check my demo here https://github.com/trungducc/stackoverflow/tree/big-title-navigation-bar

Controlling size / position of UINavigationItem titleView

Instead of using your image view as the title view, create another view that contains the image view. Set that view as the title view of the navigation item; now you’re free to adjust the image view’s frame within the title view.

Adjusting navigationItem.titleView's frame?

Sometime in between your view controller's viewWillAppear: & viewDidAppear:, the navigation bar is repositioning your titleView and resizing it to fit if necessary. It can end up uncentered because the navigation bar is prefering not to resize your titleView to fit between the buttons. It seems to try to center the title view if it's small enough, but if not will move your titleView off-center, and then I think only as last resort will resize. The effect is that the titleView is taking up all the space between the two buttons, if its textAlignment is centered then it will centered in that space though not the centered with respect to the whole screen. You can see this in your screen shot.

One answer is to make your titleView narrower so the navigation bar can center it, so try about 160 instead of 180 when you set your titleView.frame. It sucks that, when creating the view programmatically like you are, one has to put an estimate for that width into the code. What would be good is a way to maximize that space while staying centered.

It's possible to start with the titleView being the screen width, then after the navigation bar changes titleView.frame, update it again yourself in the view controller's viewDidAppear:. Using its adjusted titleView.frame.origin.x and size.width along with the screen width, you can calculate the largest of the left & right margins, then set the origin.x to that, the size.width to the screen width minus that times 2. However that doesn't take effect until after the pushed view has animated in and the shift afterwards is visible. You could hide the titleView in viewWillAppear: then unhide in viewDidAppear: after centering it, so instead of sliding in with an off-center titleView which is then shifted, it would slide in with no title which then appears.

A better possibility is to make your titleView your own subclass of UIView (or UILabel or whichever) and override setFrame to resize itself to stay centered in its superview. If I ever end up doing this myself I'll post it here. Or maybe someone else knows another place to change the titleView's frame after its been updated but before the view slides in without a view subclass.

How can I get a full-sized UINavigationBar titleView

Setting the titleView of your view's navigationItem will never do the trick. Instead, you can add a subView to the navigation controller's navigationBar :

UIView* ctrl = [[UIView alloc] initWithFrame:navController.navigationBar.bounds];
ctrl.backgroundColor = [UIColor yellowColor];
ctrl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[navController.navigationBar addSubview:ctrl];

How to resize Title in a navigation bar dynamically

Used the below code in ViewDidload .

Objective C

self.title = @"Your TiTle Text";
UILabel* tlabel=[[UILabel alloc] initWithFrame:CGRectMake(0,0, 200, 40)];
tlabel.text=self.navigationItem.title;
tlabel.textColor=[UIColor whiteColor];
tlabel.font = [UIFont fontWithName:@"Helvetica-Bold" size: 30.0];
tlabel.backgroundColor =[UIColor clearColor];
tlabel.adjustsFontSizeToFitWidth=YES;
tlabel.textAlignment = NSTextAlignmentCenter;
self.navigationItem.titleView=tlabel;

Swift Version

self.title = "Your Title Text"
let tlabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
tlabel.text = self.title
tlabel.textColor = UIColor.white
tlabel.font = UIFont.systemFont(ofSize: 30, weight: .bold)
tlabel.backgroundColor = UIColor.clear
tlabel.adjustsFontSizeToFitWidth = true
tlabel.textAlignment = .center
self.navigationItem.titleView = tlabel

Hope it works for you.Thanks



Related Topics



Leave a reply



Submit