Search code examples
iosobjective-cfontsuilabel

Dynamically changing font size of UILabel


I currently have a UILabel:

factLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 100, 280, 100)];
factLabel.text = @"some text some text some text some text";
factLabel.backgroundColor = [UIColor clearColor];
factLabel.lineBreakMode = UILineBreakModeWordWrap;
factLabel.numberOfLines = 10;
[self.view addSubview:factLabel];

Throughout the life of my iOS application, factLabel gets a bunch of different values. Some with multiple sentences, others with just 5 or 6 words.

How can I set up the UILabel so that the font size changes so that the text always fits in the bounds I defined?


Solution

  • Single line:

    factLabel.numberOfLines = 1;
    factLabel.minimumFontSize = 8;
    factLabel.adjustsFontSizeToFitWidth = YES;
    

    The above code will adjust your text's font size down to (for example) 8 trying to fit your text within the label. numberOfLines = 1 is mandatory.

    Multiple lines:

    For numberOfLines > 1 there is a method to figure out the size of final text through NSString's sizeWithFont:... UIKit addition methods, for example:

    CGSize lLabelSize = [yourText sizeWithFont:factLabel.font
                                      forWidth:factLabel.frame.size.width
                                 lineBreakMode:factLabel.lineBreakMode];
    

    After that you can just resize your label using resulting lLabelSize, for example (assuming that you will change only label's height):

    factLabel.frame = CGRectMake(factLabel.frame.origin.x, factLabel.frame.origin.y, factLabel.frame.size.width, lLabelSize.height);
    

    iOS6

    Single line:

    Starting with iOS6, minimumFontSize has been deprecated. The line

    factLabel.minimumFontSize = 8.;
    

    can be changed to:

    factLabel.minimumScaleFactor = 8./factLabel.font.pointSize;
    

    iOS7

    Multiple lines:

    Starting with iOS7, sizeWithFont becomes deprecated. Multiline case is reduced to:

    factLabel.numberOfLines = 0;
    factLabel.lineBreakMode = NSLineBreakByWordWrapping;
    CGSize maximumLabelSize = CGSizeMake(factLabel.frame.size.width, CGFLOAT_MAX);
    CGSize expectSize = [factLabel sizeThatFits:maximumLabelSize];
    factLabel.frame = CGRectMake(factLabel.frame.origin.x, factLabel.frame.origin.y, expectSize.width, expectSize.height);
    

    iOS 13 (Swift 5):

    label.adjustsFontSizeToFitWidth = true
    label.minimumScaleFactor = 0.5