Resizing UILabel to fit with Word Wrap
Here is the most elegant (yet somewhat hackish) way I found to make this work:
- Split the string into words
- Calculate the width of each word using the current font size
- Reduce the size of the string until each the word fits into one line
Resource consumption is low enough for this to work even in UITableViews
full of strings edited this way.
Here is the new code:
//Set the text
self.textLabel.text = text;
//Largest size used
NSInteger fsize = 200; textLabel.font = [UIFont fontWithName:@"Verdana-Bold"
size:fsize];
//Calculate size of the rendered string with the current parameters
float height =
[text sizeWithFont:textLabel.font
constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999)
lineBreakMode:UILineBreakModeWordWrap].height;
//Reduce font size by 5 while too large, break if no height (empty string)
while (height > textLabel.bounds.size.height and height != 0) {
fsize -= 5;
textLabel.font = [UIFont fontWithName:@"Verdana-Bold" size:fsize];
height = [text sizeWithFont:textLabel.font
constrainedToSize:CGSizeMake(textLabel.bounds.size.width,99999)
lineBreakMode:UILineBreakModeWordWrap].height;
};
// Loop through words in string and resize to fit
for (NSString *word in [text componentsSeparatedByString:@" "]) {
float width = [word sizeWithFont:textLabel.font].width;
while (width > textLabel.bounds.size.width and width != 0) {
fsize -= 3;
textLabel.font = [UIFont fontWithName:@"Verdana-Bold" size:fsize];
width = [word sizeWithFont:textLabel.font].width;
}
}
Here's my version of 0x90's answer in a category:
@implementation UILabel (MultilineAutosize)
- (void)adjustFontSizeToFit
{
//Largest size used
NSInteger fsize = self.font.pointSize;
//Calculate size of the rendered string with the current parameters
float height = [self.text sizeWithFont:self.font
constrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping].height;
//Reduce font size by 5 while too large, break if no height (empty string)
while (height > self.bounds.size.height && height > 0) {
fsize -= 5;
self.font = [self.font fontWithSize:fsize];
height = [self.text sizeWithFont:self.font
constrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping].height;
};
// Loop through words in string and resize to fit
for (NSString *word in [self.text componentsSeparatedByString:@" "]) {
float width = [word sizeWithFont:self.font].width;
while (width > self.bounds.size.width && width > 0) {
fsize -= 3;
self.font = [self.font fontWithSize:fsize];
width = [word sizeWithFont:self.font].width;
}
}
}
@end
You can use the code above in a Category for UILabel
UILabel+AdjustFontSize.h
@interface UILabel (UILabel_AdjustFontSize)
- (void) adjustsFontSizeToFitWidthWithMultipleLinesFromFontWithName:(NSString*)fontName size:(NSInteger)fsize andDescreasingFontBy:(NSInteger)dSize;
@end
UILabel+AdjustFontSize.m
@implementation UILabel (UILabel_AdjustFontSize)
- (void) adjustsFontSizeToFitWidthWithMultipleLinesFromFontWithName:(NSString*)fontName size:(NSInteger)fsize andDescreasingFontBy:(NSInteger)dSize{
//Largest size used
self.font = [UIFont fontWithName:fontName size:fsize];
//Calculate size of the rendered string with the current parameters
float height = [self.text sizeWithFont:self.font
constrainedToSize:CGSizeMake(self.bounds.size.width,99999)
lineBreakMode:UILineBreakModeWordWrap].height;
//Reduce font size by dSize while too large, break if no height (empty string)
while (height > self.bounds.size.height && height != 0) {
fsize -= dSize;
self.font = [UIFont fontWithName:fontName size:fsize];
height = [self.text sizeWithFont:self.font
constrainedToSize:CGSizeMake(self.bounds.size.width,99999)
lineBreakMode:UILineBreakModeWordWrap].height;
};
// Loop through words in string and resize to fit
for (NSString *word in [self.text componentsSeparatedByString:@" "]) {
float width = [word sizeWithFont:self.font].width;
while (width > self.bounds.size.width && width != 0) {
fsize -= dSize;
self.font = [UIFont fontWithName:fontName size:fsize];
width = [word sizeWithFont:self.font].width;
}
}
}
@end