Yeah, there\'s this cool myLabel.adjustsFontSizeToFitWidth = YES;
property. But as soon as the label has two lines or more, it won\'t resize the text to anythin
I have created Category for UILabel based on @agarcian's answer. But i calculate fontSize depending on square needed on screen for drawing text. This method not need loops and calculating is done by one iteration.
Here the .h file:
// UILabel+Extended.h
// Created by Firuz on 16/08/14.
// Copyright (c) 2014. All rights reserved.
#import <UIKit/UIKit.h>
@interface UILabel (Extended)
/** This method calculate the optimal font size for current number of lines in UILable. Mus be called after drawing UILabel view */
- (NSInteger)fontSizeWithMinFontSize:(NSInteger)minFontSize withMaxFontSize:(NSInteger)maxFontSize;
@end
And here the .m file:
// UILabel+Extended.m
// Created by Firuz on 16/08/14.
// Copyright (c) 2014. All rights reserved.
#import "UILabel+Extended.h"
@implementation UILabel (Extended)
- (NSInteger)fontSizeWithMinFontSize:(NSInteger)minFontSize withMaxFontSize:(NSInteger)maxFontSize
{
if (maxFontSize < minFontSize) {
return 0;
}
UIFont *font = [UIFont fontWithName:self.font.fontName size:maxFontSize];
CGFloat lineHeight = [font lineHeight];
CGSize constraintSize = CGSizeMake(MAXFLOAT, lineHeight);
CGRect rect = [self.text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName : font}
context:nil];
CGFloat labelSqr = self.frame.size.width * self.frame.size.height;
CGFloat stringSqr = rect.size.width/self.frame.size.width * (lineHeight + font.pointSize) * self.frame.size.width;
CGFloat multiplyer = labelSqr/stringSqr;
if (multiplyer < 1) {
if (minFontSize < maxFontSize*multiplyer) {
return maxFontSize * multiplyer;
} else {
return minFontSize;
}
}
return maxFontSize;
}
@end
Swift 3 "binary search solution" based on this answer with minor improvements. Sample is in context of UITextView
subclass:
func binarySearchOptimalFontSize(min: Int, max: Int) -> Int {
let middleSize = (min + max) / 2
if min > max {
return middleSize
}
let middleFont = UIFont(name: font!.fontName, size: CGFloat(middleSize))!
let attributes = [NSFontAttributeName : middleFont]
let attributedString = NSAttributedString(string: text, attributes: attributes)
let size = CGSize(width: bounds.width, height: .greatestFiniteMagnitude)
let options: NSStringDrawingOptions = [.usesLineFragmentOrigin, .usesFontLeading]
let textSize = attributedString.boundingRect(with: size, options: options, context: nil)
if textSize.size.equalTo(bounds.size) {
return middleSize
} else if (textSize.height > bounds.size.height || textSize.width > bounds.size.width) {
return binarySearchOptimalFontSize(min: min, max: middleSize - 1)
} else {
return binarySearchOptimalFontSize(min: middleSize + 1, max: max)
}
}
I hope that helps someone.