Search code examples
iosobjective-cuiscrollviewuilabelautolayout

Dynamic UILabel height inside UIScrollView with Autolayout


I am using autolayout with UIScrollView to show some attributes from an object. I download this information dinamically from web service. The scrollview has a constant width (because I don't want to have a vertical scroll behavior) and its subviews respect this width with a group of constraints, but I can't to increase the UILabel's height dynamically.

I code everything and I use viewDidLoad selector to create subviews...

- (void)viewDidLoad {
    [super viewDidLoad];
    .
    .
    .

    UILabel *descriptionLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    descriptionLabel.translatesAutoresizingMaskIntoConstraints = NO;
    descriptionLabel.numberOfLines = 0;
    descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
    descriptionLabel.opaque = YES;
    descriptionLabel.backgroundColor = [UIColor clearColor];
    descriptionLabel.textColor = [UIColor whiteColor];
    descriptionLabel.textAlignment = NSTextAlignmentRight;
    descriptionLabel.font = [UIFont appetitoMediumItalicFontWithSize:15.0f];
    descriptionLabel.text = NSLocalizedStringFromTable(@"APT_DISH_DETAIL_DESCRIPTION", @"DishDetail", @"Etiqueta que contiene la descripción del platillo");
    [descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    [self.detailContentScrollView addSubview:descriptionLabel];
    self.descriptionLabelS = descriptionLabel;

    .
    .
    .
}

You can watch the self.detailContentScrollView variable, this is an IBOulet created from view controller's nib.

Then I use the updateConstraints selector...

- (void)updateConstraints {
[super updateConstraints];
// This dictionary has more variables, ok
NSDictionary *viewsDict = @{@"dish_description_label": self.descriptionLabelS};
.
.
.

[self.descriptionLabelS setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.detailContentScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view1][dish_description_label]-[view2][view3][view4]-|" options:0 metrics:nil views:viewsDict]];

.
.
.
}

and finally, when I receive the web service's info, I send sizeToFit's UILabel selector and layoutIfNeeded from the scrollview. But my UILabel never resizes itself with the new content. What am I doing wrong?


Solution

  • UIScrollView content size is updated dynamically with autolayout, maybe you only must do the following

    - (void) setupScroll
    {
        [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [_contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
    
        [_scrollView addSubview:_contentView];
    
        NSArray *horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_contentView]|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:NSDictionaryOfVariableBindings(_contentView)];
        NSArray *vertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_contentView]|"
                                                                    options:0
                                                                    metrics:nil
                                                                      views:NSDictionaryOfVariableBindings(_contentView)];
    
        [_scrollView addConstraints:horizontal];
        [_scrollView addConstraints:vertical];
    
        UIView *mainView = self.view;
        horizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"|[_contentView(==mainView)]|"
                                                             options:0
                                                             metrics:nil
                                                               views:NSDictionaryOfVariableBindings(_contentView, mainView)];
    
        [mainView addConstraints:horizontal];
    }
    

    Where _contentView is your UILabel (If you have a more complex view hierarchy put on a view container) and self.view is the controller view (or anything else). Hope this helps also: iOS Autolayout with UIScrollview: Why does content view of scroll view not fill the scroll view?....

    Also don't forget to establish your UILabel preferredMaxLayoutWidth

    Cheers!