147

Is it possible to auto-resize the UILabel box/bounds to fit the contained text? (I don't care if it ends up larger than the display)

So if a user enters "hello" or "my name is really long i want it to fit in this box", it is never truncated and the label is 'widened' accordingly?

Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
wayneh
  • 4,093
  • 8
  • 29
  • 64

14 Answers14

99

Please check out my gist where I have made a category for UILabel for something very similar, my category lets a UILabel stretch it's height to show all the content: https://gist.github.com/1005520

Or check out this post: https://stackoverflow.com/a/7242981/662605

This would stretch the height, but you can change it around easily to work the other way and stretch the width with something like this, which is I believe what you want to do:

@implementation UILabel (dynamicSizeMeWidth)

- (void)resizeToStretch{
    float width = [self expectedWidth];
    CGRect newFrame = [self frame];
    newFrame.size.width = width;
    [self setFrame:newFrame];
}

- (float)expectedWidth{
    [self setNumberOfLines:1];

    CGSize maximumLabelSize = CGSizeMake(CGRectGetWidth(self.bounds), CGFLOAT_MAX);

    CGSize expectedLabelSize = [[self text] sizeWithFont:[self font] 
                                            constrainedToSize:maximumLabelSize
                                            lineBreakMode:[self lineBreakMode]]; 
    return expectedLabelSize.width;
}

@end

You could more simply use the sizeToFit method available from the UIView class, but set the number of lines to 1 to be safe.


iOS 6 update

If you are using AutoLayout, then you have a built in solution. By setting the number of lines to 0, the framework will resize your label appropriately (adding more height) to fit your text.


iOS 8 update

sizeWithFont: is deprecated so use sizeWithAttributes: instead:

- (float)expectedWidth{
    [self setNumberOfLines:1];

    CGSize expectedLabelSize = [[self text] sizeWithAttributes:@{NSFontAttributeName:self.font}];

    return expectedLabelSize.width;
}
Yaroslav Luchyt
  • 223
  • 3
  • 7
Daniel
  • 22,521
  • 12
  • 107
  • 150
  • 8
    Using the iOS 6 AutoLayout method I ended up with a height constraint on my label I couldn't get rid of. Setting the Relation of the height constraint to 'Greater Than or Equal' allowed the height to grow. – Michael Luton Oct 19 '12 at 20:53
  • 2
    sizeWithFont: constrainedToSize: lineBreakMode:method depricated in ios 7 – Karan Alangat Oct 18 '14 at 09:44
  • 1
    UILabel is not resizing itself when text is less / more. i am using Auto-layout. Tried Making UILabel but they are created everytime cellForRowAtIndex is initialised . Tried lots of things . Nothing working for me . Background of uilabel take the same width . HELp !!! – coreDeviOS Dec 23 '14 at 09:48
  • @Daniel I set the number of lines=0, but its not working. I have set the constraints of horizontally and vertically center. One extra thing I have done is made a subclass of UILABEL and using it for that Label – Jasmeet May 17 '16 at 08:53
  • With Autolayout the simplest solution to: (1) Set Lines to 0, (2) Set width constraint to "Greater Than or Equal" with Constant 0, (3) Set height constraint to "Greater Than or Equal" with Constant 0, (4) Align as you normally would, for example by centering horizontally and vertically. – Erik van der Neut Dec 19 '17 at 00:42
  • When you have hard line returns in your multi-line text, then with Autolayout the simplest solution to: (1) Set Lines to 0, (2) Set width constraint to "Greater Than or Equal" with Constant 0, (3) Set height constraint to "Greater Than or Equal" with Constant 0, (4) Align as you normally would, for example by centering horizontally and vertically. If you don't have hard line-returns in the text, but instead want to constrain it to a specific width, then under (2) set a specific "Equal" constraint instead. – Erik van der Neut Dec 19 '17 at 00:49
76

Using [label sizeToFit]; will achieve the same result from Daniels Category.

Although I recommend to use autolayout and let the label resize itself based on constraints.

Guilherme Torres Castro
  • 13,434
  • 6
  • 54
  • 95
32

If we want that UILabel should shrink and expand based on text size then storyboard with autolayout is best option. Below are the steps to achieve this

Steps

  1. Put UILabel in view controller and place it wherever you want. Also put 0 for numberOfLines property of UILabel.

  2. Give it Top, Leading and Trailing space pin constraint.

enter image description here

  1. Now it will give warning, Click on the yellow arrow.

enter image description here

  1. Click on Update Frame and click on Fix Misplacement. Now this UILabel will shrink if text is less and expand if text is more.
Community
  • 1
  • 1
Yogesh Suthar
  • 29,554
  • 17
  • 66
  • 96
25

This is not as complicated as some of the other answers make it.

enter image description here

Pin the left and top edges

Just use auto layout to add constraints to pin the left and top sides of the label.

enter image description here

After that it will automatically resize.

Notes

  • Don't add constraints for the width and height. Labels have an intrinsic size based on their text content.
  • Thanks to this answer for help with this.
  • No need to set sizeToFit when using auto layout. My complete code for the example project is here:

    import UIKit
    class ViewController: UIViewController {
    
        @IBOutlet weak var myLabel: UILabel!
    
        @IBAction func changeTextButtonTapped(sender: UIButton) {
            myLabel.text = "my name is really long i want it to fit in this box"
        }
    }
    
  • If you want your label to line wrap then set the number of lines to 0 in IB and add myLabel.preferredMaxLayoutWidth = 150 // or whatever in code. (I also pinned my button to the bottom of the label so that it would move down when the label height increased.)

enter image description here

  • If you are looking for dynamically sizing labels inside a UITableViewCell then see this answer.

enter image description here

Community
  • 1
  • 1
Suragch
  • 364,799
  • 232
  • 1,155
  • 1,198
  • Hi, I got the resized label but I don't understand how to resize of cell height. Can you please let me know how to resize cell height. – Vivek Nov 08 '17 at 11:50
  • @Vivek, as long as you don't have any constraints set on the height, it should resize automatically. – Suragch Nov 08 '17 at 12:12
  • Yes, But How It possible when I use custom cell and I put 2 label in his cell. – Vivek Nov 08 '17 at 12:14
  • @Vivek, sorry, I misread your question. Did you already get one label to work by going through [this answer](https://stackoverflow.com/a/36422189/3681880)? – Suragch Nov 08 '17 at 13:57
9

Use [label sizeToFit]; to adjust the text in UILabel

codercat
  • 21,439
  • 9
  • 56
  • 84
Gaurav Gilani
  • 1,586
  • 14
  • 18
6

Here's what I am finding works for my situation:

1) The height of the UILabel has a >= 0 constraint using autolayout. The width is fixed. 2) Assign the text into the UILabel, which already has a superview at that point (not sure how vital that is). 3) Then, do:

    label.sizeToFit()
    label.layoutIfNeeded()

The height of the label is now set appropriately.

Chris Prince
  • 6,390
  • 1
  • 38
  • 56
5

I created some methods based Daniel's reply above.

-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text
{
    CGSize maximumLabelSize     = CGSizeMake(290, FLT_MAX);

    CGSize expectedLabelSize    = [text sizeWithFont:label.font
                                constrainedToSize:maximumLabelSize
                                    lineBreakMode:label.lineBreakMode];

    return expectedLabelSize.height;
}

-(void)resizeHeightToFitForLabel:(UILabel *)label
{
    CGRect newFrame         = label.frame;
    newFrame.size.height    = [self heightForLabel:label withText:label.text];
    label.frame             = newFrame;
}

-(void)resizeHeightToFitForLabel:(UILabel *)label withText:(NSString *)text
{
    label.text              = text;
    [self resizeHeightToFitForLabel:label];
}
Doug Baker
  • 63
  • 1
  • 3
3
@implementation UILabel (UILabel_Auto)

- (void)adjustHeight {

    if (self.text == nil) {
        self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.bounds.size.width, 0);
        return;
    }

    CGSize aSize = self.bounds.size;
    CGSize tmpSize = CGRectInfinite.size;
    tmpSize.width = aSize.width;

    tmpSize = [self.text sizeWithFont:self.font constrainedToSize:tmpSize];

    self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, aSize.width, tmpSize.height);
}

@end

This is category method. You must set text first, than call this method to adjust UILabel's height.

Kaijay Lu
  • 114
  • 3
2

You can size your label according to text and other related controls using two ways-

  1. For iOS 7.0 and above

    CGSize labelTextSize = [labelText boundingRectWithSize:CGSizeMake(labelsWidth, MAXFLOAT)
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                           attributes:@{
                                                        NSFontAttributeName : labelFont
                                                        }
                                              context:nil].size;
    

before iOS 7.0 this could be used to calculate label size

CGSize labelTextSize = [label.text sizeWithFont:label.font 
                            constrainedToSize:CGSizeMake(label.frame.size.width, MAXFLOAT)  
                                lineBreakMode:NSLineBreakByWordWrapping];

// reframe other controls based on labelTextHeight

CGFloat labelTextHeight = labelTextSize.height;
  1. If you do not want to calculate the size of the label's text than you can use -sizeToFit on the instance of UILabel as-

    [label setNumberOfLines:0]; // for multiline label
    [label setText:@"label text to set"];
    [label sizeToFit];// call this to fit size of the label according to text
    

// after this you can get the label frame to reframe other related controls

Kampai
  • 21,517
  • 19
  • 87
  • 90
vijeesh
  • 1,212
  • 1
  • 16
  • 31
2
  1. Add missing constraints in storyboard.
  2. Select UILabel in storyboard and set the attributes "Line" to 0.
  3. Ref Outlet the UILabel to Controller.h with id:label
  4. Controller.m and add [label sizeToFit]; in viewDidLoad
user2941395
  • 109
  • 2
  • 2
1

I had a huge problems with auto layout. We have two containers inside table cell. Second container is resized depending on Item description (0 - 1000 chars), and row should be resized based on them.

The missing ingredient was bottom constraint for description.

I've changed bottom constraint of dynamic element from = 0 to >= 0.

  • This saved my life. If you're attempting to follow: https://github.com/honghaoz/Dynamic-Collection-View-Cell-With-Auto-Layout-Demo this is the correct answer. – Justin Fyles May 04 '16 at 02:56
0

Fits everytime! :)

    name.text = @"Hi this the text I want to fit to"
    UIFont * font = 14.0f;
    CGSize size = [name.text sizeWithAttributes:@{NSFontAttributeName: font}];
    nameOfAssessment.frame = CGRectMake(400, 0, size.width, 44);
    nameOfAssessment.font = [UIFont systemFontOfSize:font];
HannahCarney
  • 3,128
  • 1
  • 24
  • 29
0

you can show one line output then set property Line=0 and show multiple line output then set property Line=1 and more

[self.yourLableName sizeToFit];
Dixit Akabari
  • 1,959
  • 9
  • 21
-1

There's also this approach:

[self.myLabel changeTextWithAutoHeight:self.myStringToAssignToLabel width:180.0f];
Kampai
  • 21,517
  • 19
  • 87
  • 90
Dave Cole
  • 2,129
  • 1
  • 16
  • 22
  • It wasn't me who downvoted this answer but I just wanted to point out that I cannot see a `changeTextWithAutoHeight:width:` method on `UILabel`. Could you provide a link please to where in the UIKit documentation this method can be found. – Adil Hussain Feb 26 '19 at 14:44