iOS resize styled UILabel dynamically

10,972

There might be a few problems here.

  • First of all, when you say this:

I autoresize the height of the scrollview after calling sizeToFit. The view mode of the scrollview is set to Scall to Fill and Autoresize subviews is turned on.

that might be a problem. Calling sizeToFit is attempting to resize your labels. But, if you later resize the scroll view, and your scroll view is set to Autoresize Subviews, then it might resize the label again. sizeToFit should be the last resizing you do on your label.

  • Also, when you say "autoresize the height of the scrollview", I'm not 100% sure what you mean. What I think you should do is after you get your JSON response, determine how big the size of all your labels are, and then set the scroll view's content size. The frame size (height) of the scroll view should not change.

  • If you read the UILabel documentation, it says:

adjustsFontSizeToFitWidth

Important: If this property is set to YES, it is a programmer error to set the lineBreakMode property to a value that causes text to wrap to another line.

So, you probably shouldn't be setting that property (Autoshrink), if the label is set to word wrap, too.

Solution

Anyway, I know you're using storyboards, but hopefully the code example below can show you how this should work:

- (void)viewDidLoad
{
   [super viewDidLoad];
   // Do any additional setup after loading the view from its nib.
   self.scrollView.autoresizesSubviews = YES;
   self.scrollView.contentMode = UIViewContentModeScaleToFill;

   // simulate a network delay of 4 seconds to fetch JSON
   double delayInSeconds = 4.0;
   dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
   dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
      // we have the "JSON" data
      int dfltLabelHeight = 250;  // will be resized!
      int yPadding = 10;
      int y = yPadding;
      int numLabels = 8;

      for (int i = 0; i < numLabels; i++) {
         UILabel* label = [[UILabel alloc] initWithFrame: CGRectMake(0, y,
                                                                     self.scrollView.frame.size.width, dfltLabelHeight)];
         label.lineBreakMode = NSLineBreakByWordWrapping;
         label.minimumFontSize = 10;
         label.autoresizesSubviews = YES;  // doesn't matter here
         //label.adjustsFontSizeToFitWidth = YES;
         //label.adjustsLetterSpacingToFitWidth = NO;  // this crashes on iOS 6.1
         label.numberOfLines = 0;
         label.text = @"Nam nisi arcu, sodales vitae scelerisque sit amet. Nam nisi arcu, sodales vitae scelerisque sit amet. Nam nisi arcu, sodales vitae scelerisque sit amet.";
         [self.scrollView addSubview: label];
         [label sizeToFit];

         // re-center the label horizontally
         CGRect frame = label.frame;
         frame.origin.x = (self.scrollView.frame.size.width - frame.size.width) / 2;
         label.frame = frame;

         y += yPadding + label.frame.size.height;
      }

      // adjust scroll view's virtual (content) size to fit the labels
      self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, y);
   });
}

Results

enter image description here

Share:
10,972
Danny Hiemstra
Author by

Danny Hiemstra

Ruby software engineer @ fitmo.com

Updated on June 04, 2022

Comments

  • Danny Hiemstra
    Danny Hiemstra almost 2 years

    I have added a UILabel with a fixed with and initial height to the bottom of my scrollview via the storyboard. Via the UIViewContoller I give the UILabel a white background and rounded corners and load text into the label dynamically.

    What I want to do is resize the label height based on the text. I have read tons of posts on stackoverflow on how to do this and tried them all and none of them seem to work.

    To bring down the problem I use the following code:

    descriptionLabel.numberOfLines = 0;
    descriptionLabel.text = @"Nam nisi arcu, sodales vitae scelerisque sit amet. Nam nisi arcu, sodales vitae scelerisque sit amet. Nam nisi arcu, sodales vitae scelerisque sit amet.";
    [descriptionLabel sizeToFit];
    

    The result of this is that the label will cut of the text like this: enter image description here

    What comes up in my mind is sizeToFit uses the initial height of the UILabel to determine the max height so in the storyboard I changed this to 250. The result is very strange, the text is placed vertically aligned in the label, like this:

    enter image description here

    (I can't show the whole height of the label because the scrollView cuts it off)

    If I NSLog the height of the UILabel after sizeToFit, I properly get to see that the height of the label is 105 pixels but the label is definitely not shown with that height.

    I would highly appreciate some help because this problem is keeping me busy for a week now.


    Update: Some additional info as requested.

    The code that resizes the UILabel is called after receiving some JSON from the server via RESTkit. viewDidLoad executes the function that loads the data via dispatch_async().

    The properties of the label are:

    Line breaks: word wrap
    Autoshrink: Min font size (10)
    Tightening letter spacing is off and Autoresize subviews is turned on.

    The container that holds the UILabel is the UIScrollView. I autoresize the height of the scrollview after calling sizeToFit.

    The view mode of the scrollview is set to Scale to Fill and Autoresize subviews is turned on.

  • Danny Hiemstra
    Danny Hiemstra about 11 years
    thnx for your great answer. Drawing the Label programmatically after the rest of the screen was loaded did solve my problem.
  • Nate
    Nate about 11 years
    Great news. Glad I could help.