How to resize Title in a navigation bar dynamically
Asked Answered
Q

11

25

I have some views that show up in a navigation controller. Two of these views have a longer title for the navigation bar.

The problem is that when the title is too long to fit, some characters are truncated and "..." is added.

Is there any way I can tell the Navigation bar to re-size the title text automatically to fit?

Quiteris answered 19/2, 2013 at 11:38 Comment(1)
Check this link #2422883 It will solves your problem hopefully.Inexpressible
A
40

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

Antecedent answered 19/2, 2013 at 16:26 Comment(1)
In iOS 14, another answer here offers a more native-looking solution than this one: https://mcmap.net/q/525913/-how-to-resize-title-in-a-navigation-bar-dynamicallyElstan
O
12

Swift version of Accepted Answer + putting the label text on center :

Swift 2.3:

    self.title = "Your TiTle Text"
    let tlabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
    tlabel.text = self.title
    tlabel.textColor = UIColor.whiteColor()
    tlabel.font = UIFont.boldSystemFontOfSize(17) //UIFont(name: "Helvetica", size: 17.0)
    tlabel.backgroundColor = UIColor.clearColor()
    tlabel.adjustsFontSizeToFitWidth = true
    tlabel.textAlignment = .Center
    self.navigationItem.titleView = tlabel

And Swift 3 :

    self.title = "Your TiTle Text"
    let frame = CGRect(x: 0, y: 0, width: 200, height: 40)
    let tlabel = UILabel(frame: frame)
    tlabel.text = self.title
    tlabel.textColor = UIColor.white
    tlabel.font = UIFont.boldSystemFont(ofSize: 17) //UIFont(name: "Helvetica", size: 17.0)
    tlabel.backgroundColor = UIColor.clear
    tlabel.adjustsFontSizeToFitWidth = true
    tlabel.textAlignment = .center
    self.navigationItem.titleView = tlabel
Onstad answered 16/11, 2016 at 14:17 Comment(0)
H
4

This works for me

Objective C

[UILabel appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class]]].adjustsFontSizeToFitWidth = YES;

Swift Version

UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).adjustsFontSizeToFitWidth = true
Hyunhz answered 13/9, 2021 at 15:3 Comment(2)
Short and sweet! And it works.Frasier
Tested and working on iOS 15 with largeTitles.Dorthea
S
2

In case you have a view added into titleView, and you want to resize the view, you can use this code (Swift 3):

self.translatesAutoresizingMaskIntoConstraints = false
self.layoutIfNeeded()
self.sizeToFit()
self.translatesAutoresizingMaskIntoConstraints = true
Shandy answered 13/9, 2017 at 22:27 Comment(0)
S
1

None of the above solutions seam to work reliably for me. However I found a solution by using different elements of the provides answers, its in Swift 2 and is really elegant as it does not require any custom code each time you change the label, it just uses property observers on the title.

Note that in my case, I had a back button on the left side of the navigation bar, which putted the text out of the center of the screen, to fix this I am using attributed text and the tailIndent. All comments/info in the code below :

class VCHowToTopic : UIViewController {


    //add handlers so that any manipulation of the title is caught and transferred to the custom drawn UILabel
    override var title : String? {
        set {
            super.title = newValue
            configureTitleView()
        }
        get {
            return super.title
        }
    }

    //MARK: - lifecycle


    func configureTitleView() {
        //some large number that makes the navigationbar schrink down our view when added
        let someVeryLargeNumber = CGFloat(4096)
        //create our label
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: someVeryLargeNumber, height: someVeryLargeNumber))
        //0 means unlimited number of lines
        titleLabel.numberOfLines = 0
        //define style of the text (we will be using attributed text)
        let style = NSMutableParagraphStyle()
        style.alignment = .Center
        //top compensate for the backbutton which moves the centered text to the right side of the screen
        //we introduce a negative tail indent, the number of 56 has been experimentally defined and might
        //depend on the size of your custom back button (if you have one), mine is 22x22 px
        style.tailIndent = -56
        //create attributed text also with the right color
        let attrText = NSAttributedString(string: title!, attributes: [NSParagraphStyleAttributeName : style,
            NSForegroundColorAttributeName : UIColor.whiteColor()])
        //configure the label to use the attributed text
        titleLabel.attributedText = attrText
        //add it as the titleview
        navigationItem.titleView = titleLabel
    }


}
Stencil answered 4/9, 2016 at 6:51 Comment(1)
CGRect(x: 0, y: 0, width: someVeryLargeNumber, height: someVeryLargeNumber) is the key to make the view visible in the TitleHomesick
C
1

Swift 5 and iOS 13 / iOS 14

The answers from above don't work if you have a large title in Swift 5 and iOS 13 because they simply add another title to your navigation bar. Instead you could use the largeTitleTextAttributes property (available since iOS 11) to shrink your title when needed.
Assuming you have set your large title via storyboard or code already, you can use the following method:

private func configureNavigationTitle(_ title: String) {
        let tempLabel = UILabel()
        tempLabel.font = UIFont.systemFont(ofSize: 34, weight: .bold)
        tempLabel.text = title

        if tempLabel.intrinsicContentSize.width > UIScreen.main.bounds.width - 30 {
            var currentTextSize: CGFloat = 34
            for _ in 1 ... 34 {
                currentTextSize -= 1
                tempLabel.font = UIFont.systemFont(ofSize: currentTextSize, weight: .bold)
                if tempLabel.intrinsicContentSize.width < UIScreen.main.bounds.width - 30 {
                    break
                }
            }
            navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: currentTextSize, weight: .bold)]
        }
        self.title = title
    }

So essentially we are ussing a helper label in order to get the width of our title and then we are going to shrink the font size until the title fits in our navigation bar. Call it from viewDidLoad():

override func viewDidLoad() {
        super.viewDidLoad(
        configureNavigationTitle("A very long title which fits perfectly fine")
    }
Camenae answered 27/5, 2020 at 12:49 Comment(0)
B
1

You can create a UILabel as UINavigationItem's titleView and set it's adjustsFontSizeToFitWidth to true.

class MyViewController: UIViewController {
    override var title: String? {
        didSet {
            (self.navigationItem.titleView as? UILabel)?.text = self.title
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.titleView = UILabel().apply {
            $0.font = .boldSystemFont(ofSize: 18)
            $0.minimumScaleFactor = 0.5
            $0.adjustsFontSizeToFitWidth = true
            $0.text = self.title
        }
    }
}

Easy to use:

myViewController.title = "This is a long title, but don’t worry."

The apply closure in the above code is a trick, in order to make the programming experience better. There is also a with closure. Recommend to everyone.

protocol ScopeFunc {}

extension ScopeFunc {
    @inline(__always) func apply(_ block: (Self) -> ()) -> Self {
        block(self)
        return self
    }

    @inline(__always) func with<R>(_ block: (Self) -> R) -> R {
        return block(self)
    }
}

extension NSObject: ScopeFunc {}
Bosch answered 10/7, 2020 at 11:7 Comment(0)
U
0

you need to customize the navigation bar title view with uilabel and provide adjust font size..

    [self.navigationItem setTitleView:<"Include any UI View subclass">];
Upturn answered 19/2, 2013 at 11:40 Comment(0)
G
0

Just calling sizeToFit() on my view after the change worked for me

Gamo answered 10/11, 2022 at 15:0 Comment(0)
W
-1

Here's an example in Swift that also allows for multiple lines. Using PureLayout to simplify auto layout.

override func viewDidLoad() {
  super.viewDidLoad()
  configureTitleView()
}

func configureTitleView() {
  let titleLabel = UILabel()
  titleLabel.numberOfLines = 0
  titleLabel.textAlignment = .Center
  titleLabel.font = UIFont.boldSystemFontOfSize(17.0)
  titleLabel.text = searchLoc.mapItem.name
  navigationItem.titleView = titleLabel
  titleLabel.autoPinEdgesToSuperviewMargins() // PureLayout method
  titleLabel.adjustsFontSizeToFitWidth = true
}

And a usage example:

enter image description here

Winshell answered 27/5, 2015 at 15:41 Comment(1)
does not seam to work because when the titleLabel.autoPinEdgesToSuperviewMargins is called, the superview of the titleLabel is (still) nil and thus setting the constraints asserts. (xcode 7.3, IOS9)Stencil
G
-1

Swift 4 and iOS 13

Adding this so my future self can find it. Views added to titleView for some reason don't like to automatically resize themselves. So you have to do it manually.

Example

(navigationItem.titleView as? UILabel)?.text = "A longer string..." // label not resized and text is cut off

Solution

navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = false
navigationItem.titleView?.setNeedsLayout()
navigationItem.titleView?.layoutIfNeeded()
navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = true

Thanks to @Paolo Musolino for leading me here.

Gadwall answered 30/4, 2020 at 20:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.