Resize Multi-line Text to Fit UILabel on iPhone

The UILabel is a great tool for displaying lines of text in any view and is easy to set up using the provided Interface Builder. Unfortunately, there is a deceptive option in the Label Attributes that says "Font Size: Adjust To Fit." This is a great feature because it means that the iPhone will automatically resize your text down in order to fit all of it into the label. Unfortunately, this feature only works when your label's layout is set to single-line. If your text is multiline like ours was, it won't adjust the font size at all!

Well we did some brief searching around to locate a solution to this problem but ended up simply writing our own. We have the following situation:

  • We have dynamic text, the exact quantity of which varies.
  • We want to place that text in a fixed-width and fixed-height UILabel
  • We don't want the text to get cutoff if it doesn't fit perfectly

In order to meet this challenge, we wrote some simple code to automatically resize the text.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//Create a string with the text we want to display.
self.ourText = @"This is your variable-length string. Assign it any way you want!";
 
/* This is where we define the ideal font that the Label wants to use.
   Use the font you want to use and the largest font size you want to use. */
UIFont *font = [UIFont fontWithName:@"Marker Felt" size:28];
 
int i;
/* Time to calculate the needed font size.
   This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
   Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
for(i = 28; i > 10; i=i-2)
{
	// Set the new font size.
	font = [font fontWithSize:i];
	// You can log the size you're trying: NSLog(@"Trying size: %u", i);
 
	/* This step is important: We make a constraint box 
	   using only the fixed WIDTH of the UILabel. The height will
	   be checked later. */ 
	CGSize constraintSize = CGSizeMake(260.0f, MAXFLOAT);
 
	// This step checks how tall the label would be with the desired font.
	CGSize labelSize = [self.ourText sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
 
	/* Here is where you use the height requirement!
	   Set the value in the if statement to the height of your UILabel
	   If the label fits into your required height, it will break the loop
	   and use that font size. */
	if(labelSize.height <= 180.0f)
		break;
}
// You can see what size the function is using by outputting: NSLog(@"Best size is: %u", i);
 
// Set the UILabel's font to the newly adjusted font.
msg.font = font;
 
// Put the text into the UILabel outlet variable.
msg.text = self.ourText;

To use the above text, you need to make a "IBOutlet UILabel *msg;" which you assign as the UILabel's Reference Outlet from the interface builder.

And there you have it: easy automatic resizing of multi-line text to fit in your fixed-size UILabel for the iPhone using Objective-C!

22 Responses to “Resize Multi-line Text to Fit UILabel on iPhone”

  1. Ajay says:

    Thanks very much.
    It works great.

  2. samF says:

    Thanks. An explanation to mysterious failure-to-resize behavior, and a solution all in one!

  3. Kelli Garner says:

    Thats very good to know... thanks

  4. JFGDev says:

    Code works great! Ran into same issue and thought it was a bug in 3.0. Thanks for the well-commented code--was very simple to implement.

  5. Jim says:

    Wow! Finally something simple that works first time. Thanks for the great explanation and code. I still haven't cracked how to get the type to anchor from the top left of the UILabel. Annoyingly, it centres on the height. I guess that's for another day.

  6. Andrew says:

    I had this problem and your code helped me solve it instantly, thanks!

  7. Rich Leland says:

    Thanks for this post! Exactly what I was looking for.

  8. Cameron says:

    Thanks for this! I thought I was losing my mind..

  9. Kabrett says:

    I was looking for a solution for this problem so long. Thanks so much for this piece of code ...

  10. Joe says:

    I was pretty sure that's how it had to be done, but as a beginner in Objective-C it's not always so simple to implement without being intimate with all of the objects and their methods yet.

    Thanks for the Example, it was exactly what I was looking for. I was a little surprised that this capability wasn't built-in to UILabel. Seems like a common scenario that we all run in to at some point or another.

  11. Alekos says:

    Great post, just what I was looking for, saved me from quite some trouble

  12. Matt says:

    This is a great piece of code. Simple, elegant, and well documented. Thank you so much.

  13. [...] i found a workaround from a blog post. Here comes to the [...]

  14. hac76 says:

    Thanks a lot i've made a UIFONT class extension if you want to post it on this page mail me

  15. GammaPoint says:

    Thanks. Good write-up. Works well.

  16. Steve N. says:

    Here's a slightly modified version that has been refactored as a static helper method:

    + (void)resizeFontForLabel:(UILabel*)aLabel maxSize:(int)maxSize minSize:(int)minSize {
    // use font from provided label so we don't lose color, style, etc
    UIFont *font = aLabel.font;

    // start with maxSize and keep reducing until it doesn't clip
    for(int i = maxSize; i > 10; i--) {
    font = [font fontWithSize:i];
    CGSize constraintSize = CGSizeMake(aLabel.frame.size.width, MAXFLOAT);

    // This step checks how tall the label would be with the desired font.
    CGSize labelSize = [aLabel.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
    if(labelSize.height <= aLabel.frame.size.height)
    break;
    }
    // Set the UILabel's font to the newly adjusted font.
    aLabel.font = font;
    }

  17. daniele says:

    REALLY GREAT, here an implementation sublassing UILabel

    -(void)adjustFontToFitMultiline{

    NSString *stringTmp = self.text;

    //Create a string with the text we want to display.

    /* This is where we define the ideal font that the Label wants to use.
    Use the font you want to use and the largest font size you want to use. */
    UIFont *font = self.font;

    int i;
    /* Time to calculate the needed font size.
    This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
    Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
    int pointSizeMax = font.pointSize;
    int pointSizeMin = self.minimumFontSize;

    for(i = pointSizeMax; i > pointSizeMin; i=i-2)
    {
    // Set the new font size.
    font = [font fontWithSize:i];
    // You can log the size you're trying: NSLog(@"Trying size: %u", i);

    /* This step is important: We make a constraint box
    using only the fixed WIDTH of the UILabel. The height will
    be checked later. */
    CGSize constraintSize = CGSizeMake(79.0f, MAXFLOAT);

    // This step checks how tall the label would be with the desired font.
    CGSize labelSize = [stringTmp sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    /* Here is where you use the height requirement!
    Set the value in the if statement to the height of your UILabel
    If the label fits into your required height, it will break the loop
    and use that font size. */
    if(labelSize.height <= 39.0f)
    break;
    }
    // You can see what size the function is using by outputting: NSLog(@"Best size is: %u", i);

    // Set the UILabel's font to the newly adjusted font.
    self.font = font;

    // Put the text into the UILabel outlet variable.

    }

    call in this manner

    myLabel.text = @"sasasas";
    [myLabel adjustFontToFitMultiline];

  18. Abhi says:

    Thanks. Great help..!!!!!

  19. dacapo says:

    Thanks for the great code! This was exactly what I needed.

  20. Regis says:

    Does somebody have a similar code to adapt the text size to a NSTextField in Cocoa ?

  21. Anonymous says:

    Wah, big thanks to you!:)

  22. [...] i found a workaround from a blog post. Here comes to the solution. [...]

Leave a Reply