Swift - Adjusting fontSize to fit the width of the layout (programmatically) Swift - Adjusting fontSize to fit the width of the layout (programmatically) xcode xcode

Swift - Adjusting fontSize to fit the width of the layout (programmatically)


Try the following commands for your label:

label.adjustsFontSizeToFitWidth = truelabel.minimumScaleFactor = 0.2

And try to change the lines of the label to 0 and 1 (check both cases):

label.numberOfLines = 0 // or 1


MinimumScaleFactor range is 0 to 1. So we are setting the MinimumScaleFactor with respect to our font size as follows

Objective C

[lb setMinimumScaleFactor:10.0/[UIFont labelFontSize]];lb.adjustsFontSizeToFitWidth = YES;

Swift 3.0

lb.minimumScaleFactor = 10/UIFont.labelFontSizelb.adjustsFontSizeToFitWidth = true


I don't know if this will completely answer your question, but you can use this extension to calculate your own font sizes to fit.

Swift 3

extension String {   func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat {       let constraintSize = CGSize(width: width, height: .max)       let boundingBox = self.boundingRectWithSize(constraintSize, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)       return boundingBox.height   }   func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat {       let constrainedSize = CGSize(width: .max, height: height)       let boundingBox = self.boundingRectWithSize(constrainedSize, options: .UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)       return boundingBox.width   }}

Update - Adds example and updates code to Swift 5

Swift 5

extension String {    func height(constrainedBy width: CGFloat, with font: UIFont) -> CGFloat {        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)        return boundingBox.height    }    func width(constrainedBy height: CGFloat, with font: UIFont) -> CGFloat {        let constrainedRect = CGSize(width: .greatestFiniteMagnitude, height: height)        let boundingBox = self.boundingRect(with: constrainedRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: font], context: nil)        return boundingBox.width    }}

Here is my logic to make sure that two different labels had the same font size. In my case it was two labels for the user's first and last name. The reason I needed two labels for this, is because each label is independently animated.

class ViewController: UIViewController {      ...      func viewDidLoad() {         super.viewDidLoad()         fixFontSizes()         ...      }      func fixFontSizes() {         let leadingMargin = self.leadingContainerConstraint.constant         let trailingMargin = self.trailingContainerConstraint.constant         let maxLabelWidth = self.view.bounds.width - leadingMargin - trailingMargin         let firstName = self.firstNameLabel.text ?? ""         let lastName = self.lastNameLabel.text ?? ""         let firstNameWidth = firstName.width(constrainedBy: self.container.bounds.height, with: self.firstNameLabel.font)         let lastNameWidth = lastName.width(constrainedBy: self.container.bounds.height, with: self.lastNameLabel.font)         let largestLabelWidth = max(firstNameWidth, lastNameWidth)         guard largestLabelWidth > maxLabelWidth else { return }         let largestTextSize = max(self.firstNameLabel.font.pointSize, self.lastNameLabel.font.pointSize)         let labelToScreenWidthRatio = largestLabelWidth / maxLabelWidth         let calculatedMaxTextSize = floor(largestTextSize / labelToScreenWidthRatio)         self.firstNameLabel.font = self.firstNameLabel.font.withSize(calculatedMaxTextSize)         self.lastNameLabel.font = self.lastNameLabel.font.withSize(calculatedMaxTextSize)      }}