How to Calculate Actual Font Point Size in iOS 7 (Not the Bounding Rectangle)

How do I get auto-adjusted font size in iOS 7.0 or later?

Swift 4

The answers above work well, but use some deprecated values/functions. Here's a fixed version that works in 2018.

func approximateAdjustedFontSizeWithLabel(_ label: UILabel) -> CGFloat {
var currentFont: UIFont = label.font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (label.text! as NSString).size(withAttributes: [NSAttributedStringKey.font: currentFont])

while currentSize.width > label.frame.size.width && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor) {
currentFont = currentFont.withSize(currentFont.pointSize - 1.0)
currentSize = (label.text! as NSString).size(withAttributes: [NSAttributedStringKey.font: currentFont])
}

return currentFont.pointSize
}

iOS UILabel bounding rectangle not sized correctly

That looks like a bug. If you increase your base font size, you will see the space increase. Also, if you inspect the layout at runtime, you will see the content size to be calculated as too big.

My guess is, UILabel takes your original font size (40) to calculate the content size for 3 lines of text and does not take into account that the font size has already been decreased before truncation.

I fiddled with content hugging/compression priorities but could not make it work either.

The only workaround I found was to manually set the font size down to 20. That will get you the frame you want.

How to calculate the width of a text string of a specific font and font-size?

You can do exactly that via the various sizeWithFont: methods in NSString UIKit Additions. In your case the simplest variant should suffice (since you don't have multi-line labels):

NSString *someString = @"Hello World";
UIFont *yourFont = // [UIFont ...]
CGSize stringBoundingBox = [someString sizeWithFont:yourFont];

There are several variations of this method, eg. some consider line break modes or maximum sizes.

UILabel get the displayed font size when adjustsFontSizeToFitWidth is YES

Turns out it is a bit more complex since iOS 7 deprecated the useful sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:, as used in the suggested duplicate.

We now have to use NSAttributedString instead.

Create an NSAttributedString from the string to be / that is set on the label. Setting the entire attributed string's font to whatever the label's font is.

NSDictionary *attributes = @{NSFontAttributeName : self.label.font};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text
attributes:attributes];

Then, create a NSStringDrawingContext object, configured to use the minimum scale factor of the label. This will be used to assist in the calculation of the actual font size.

NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
context.minimumScaleFactor = self.label.minimumScaleFactor;

We can then use the NSAttributedString method to calculate the bounding rect, and further configure the NSStringDrawingContext:

[attributedString boundingRectWithSize:self.label.bounds.size
options:NSStringDrawingUsesLineFragmentOrigin
context:context];

This will make a drawing pass and the context will be updated to include the scale factor that was used in order to draw the text in the space available (the label's size).

Getting the actual font size is then as simple as:

CGFloat actualFontSize = self.label.font.pointSize * context.actualScaleFactor;


Related Topics



Leave a reply



Submit