Reputation: 1451
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:
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
Reputation: 4919
All you need is:
UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).adjustsFontSizeToFitWidth = true
Working also with SwiftUI on iOS 15.
Upvotes: 24
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
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
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
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