1
votes

Please review this easy example of dynamic multiline UILabel with Autolayout that should force its superview to grow in height. The example is working fine in portrait orientation, while in landscape the UILabel grows too much in height.

I set constraints in storyboard, vertical compression and hugging priority of the label is 1000, the superview's is 1. All other top, bottom, leading and trailing constraints inbetween views are standard.

I have colored the background of the label with very lightgray color so it is clear that the label's top and bottom margins are much bigger than in portrait mode. Can somebody please advise how can I get the label with same top and bottom margins in landscape as well? Thanks.

enter image description here

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.myTextLabel.text = @"iPhone 6 rumoured to have larger display.";
}

- (IBAction)button:(UIButton *)sender
{
    if (!self.flag) {
        self.innerHeightConstraint.constant = 120.0;
        self.myTextLabel.text = @"iPhone 6 rumoured to have larger, 1704 x 960 display. A new report indicates that Apple's testing it.";
        self.flag = YES;
    } else {
        self.innerHeightConstraint.constant = 60.0;
        self.myTextLabel.text = @"iPhone 6 rumoured to have larger display.";
        self.flag = NO;
    }
    [self.view layoutIfNeeded];
}
2

2 Answers

5
votes

I think that you're hitting a specific thing with multiline labels and auto layout. For the detailed explanation see Advanced Auto Layout Toolbox (Intrinsic Content Size of Multi-Line Text).

The quick-fix is to put this in your view controller:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [self.view layoutIfNeeded];
}

Though I would recommend to use the custom label class or overriding layoutSubviews in the container view solutions described in the link.

0
votes

I have resolved it with direct calculation of the UILabel height in boundingRectWithSize: method, but this is a shortcut avoiding the purpose of having Autolayout, so I would still appreciate any feedback on this.

NSDictionary *attributes = @{NSFontAttributeName : [UIFont systemFontOfSize:16.0]};
CGRect textLabelRect = [self.myTextLabel.text boundingRectWithSize:CGSizeMake(self.view.bounds.size.width - 40.0, 9999.0) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:attributes context:nil];

CGFloat height = textLabelRect.size.height + someMagicNumber;