Tigran Iskandaryan
Tigran Iskandaryan

Reputation: 1451

My navigation bar's large title is too wide. How to fix that?

I am using navigation controller, and I've set to true its navigation bar's prefersLargeTitle property. Everything works fine, but when the text of my title becomes too big, it doesn't fit in space. Here how it looks:

enter image description here

Is it possible to somehow make the title (while the navigation bar's prefersLargeTitle property is set to true) dynamically adjust its font size, and if it is so, how to achieve that?

Upvotes: 18

Views: 9524

Answers (5)

Sound Blaster
Sound Blaster

Reputation: 4919

All you need is:

UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).adjustsFontSizeToFitWidth = true

Working also with SwiftUI on iOS 15.

Upvotes: 24

andrew54068
andrew54068

Reputation: 1406

Tested for iOS12 ~ iOS14

extension UINavigationController {

    func adjustFontSize(with title: String) {
        let insetToEdge: CGFloat = 16
        let maxWidth = navigationBar.bounds.width - insetToEdge - insetToEdge
        let largeTitleFont = UIFont.preferredFont(forTextStyle: .largeTitle)
        var fontSize = largeTitleFont.pointSize

        var largeTitleTextAttributes: [NSAttributedString.Key: Any] = [:]

        var largeTitleSize: CGSize
        if #available(iOS 13.0, *) {
            largeTitleSize = NSAttributedString(
                string: title,
                attributes: navigationBar.standardAppearance.largeTitleTextAttributes)
                .size()
        } else {
            largeTitleTextAttributes = [NSAttributedString.Key.font: largeTitleFont]
            largeTitleSize = NSAttributedString(
                string: title,
                attributes: largeTitleTextAttributes)
                .size()
        }
        guard largeTitleSize.width > maxWidth else { return }
        while largeTitleSize.width > maxWidth {
            fontSize -= 1
            if #available(iOS 13.0, *) {
                largeTitleTextAttributes = navigationBar.standardAppearance.largeTitleTextAttributes
            }
            largeTitleTextAttributes[NSAttributedString.Key.font] = UIFont.BO.font(
                ofSize: fontSize,
                weight: .semiBold)
            largeTitleSize = NSAttributedString(
                string: title,
                attributes: largeTitleTextAttributes)
                .size()
        }
        if #available(iOS 13.0, *) {
            navigationBar.standardAppearance.largeTitleTextAttributes = largeTitleTextAttributes
        } else {
            navigationBar.largeTitleTextAttributes = largeTitleTextAttributes
        }
    }

}

call from viewDidLoad()

Upvotes: 0

Paresh Masani
Paresh Masani

Reputation: 7504

Made an edit to @vicente.fava answer - this works great.

self.title = longTitle
self.navigationController?.navigationBar.prefersLargeTitles = true
adjustLargeTitleSize()


extension UIViewController {
func adjustLargeTitleSize() {
    guard let title = title, #available(iOS 11.0, *) else { return }

    let maxWidth = UIScreen.main.bounds.size.width - 60
    var fontSize = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
    var width = title.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)]).width

    while width > maxWidth {
        fontSize -= 1
        width = title.size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)]).width
    }

    navigationController?.navigationBar.largeTitleTextAttributes =
        [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: fontSize)
    ]
}

}

Upvotes: -1

vicente.fava
vicente.fava

Reputation: 370

This is the workaround that I found

override func viewDidLoad() {
  super.viewDidLoad()

  title = yourTitle
  adjustLargeTitleSize()
}

extension UIViewController {
  func adjustLargeTitleSize() {
    guard let title = title, #available(iOS 11.0, *) else { return }

    let maxWidth = UIScreen.main.bounds.size.width - 60
    var fontSize = UIFont.preferredFont(forTextStyle: .largeTitle).pointSize
    var width = title.size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize)]).width

    while width > maxWidth {
      fontSize -= 1
      width = title.size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize)]).width
    }

    navigationController?.navigationBar.largeTitleTextAttributes =
        [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: fontSize)
    ]
  }
}

Upvotes: 22

casperson
casperson

Reputation: 146

This question is somewhat answered here: How to resize Title in a navigation bar dynamically.

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(name: "Helvetica-Bold", size: 30.0)
tlabel.backgroundColor = UIColor.clearColor()
tlabel.adjustsFontSizeToFitWidth = true
self.navigationItem.titleView = tlabel

That being said, this is slightly different, in that you have the prefersLargeTitle property set. Now, I am not sure whether the tlabel.adjustsFontSizeToFitWidth = true overrides the prefersLargeTitle property, but try it out and see if it works. There is also some additional information regarding navigation item large titles here: https://developer.apple.com/documentation/uikit/uinavigationitem/2909056-largetitledisplaymode. Hope this helps.

Upvotes: 3

Related Questions