Question

I am trying to replicate a fluid vertical layout with autolayout in ios7. The problem is that i am using a stack of UILabels (and others elements) with AttributedStrings (but this seems to not to interfere with the issue since it also comes with plain text) and the text in the labels is added dynamically, but the frame, or better the constraints don't seems to adapt in a correct way automatically (not specifying a height for the labels) since the label remain of the dimensions given in the xib.

Initial configuration in the Xib, blue are setted equality constraints

Initial configuration in the Xib, blue are setted equality constraints

Same if i use to set a big height constraint constant with value lower of the compression and hugging priority. Nothing change.

After adding text and resizing constraint value (the text should have 5 rows)

After adding text and resizing constraint value (the text should have 5 rows

I finally tryed recreating the contraint every time the text change either this way or with CoreText or many others methods

[self.view setAutoresizesSubviews:NO];
label.lineBreakMode = NSLineBreakByWordWrapping;
label.numberOfLines = 0;
label.preferredMaxLayoutWidth = label.frame.size.width;

[label removeConstraint:oldConstraint];

NSInteger height = ceil([label.attributedText
               boundingRectWithSize:CGSizeMake(label.frame.size.width, 10000)
               options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
               //TODO 20 or 1.5 is an hardoced value. find solution to workaround
               //attributes:@{NSFontAttributeName:[UIFont fontWithName:kFontCrimsonText_Roman size:17]}
               context:nil].size.height) + 1;

NSLayoutConstraint * newConstraint = [NSLayoutConstraint constraintWithItem:label
                                                                  attribute:NSLayoutAttributeHeight
                                                                  relatedBy:NSLayoutRelationEqual
                                                                     toItem:nil
                                                                  attribute:NSLayoutAttributeNotAnAttribute
                                                                 multiplier:1.0f
                                                                   constant:height];
[label addConstraint:newConstraint];

This time the dimensions of the labels seems correct but the text inside it is not displayed properly:

Lets say i have a text of 5 rows only the first are shown and the lasts are just cutted despite the fact the the frame seems to be perfectly fitting the required dimensions.

the red space remains in any case

Multiplying the height by 2 (or another constant) seems to fix the problem but obviously now the text is more little than the frame and a lot of blank space remain on top and bottom.

Trying with [label fitToSize] seems to works perfectly, but obviously the constraints bring the frame back right after.

What is the best practice to achieve a vertical fluid layout with dynamic UIlabels and autolayout?

Was it helpful?

Solution 2

I ended up finding this was a bug, due to use of AttributedText in a UILabel with Autolayout turned on, in ios7.

A temporary workaround as sugested in the other question was to append a new-line character to the attributed string and reducing "bottom margins".

Another one is tu use textview.

Bug reported also in:
- Lines missing from tall UILabel when embedding NSTextAttachment
- iOS 7 BUG - NSAttributedString does not appear

OTHER TIPS

The best way to create a "fluid vertical layout"... UITableView.

Seriously, this looks like a perfect candidate for using a UITableView.

It is useful for more than just displaying lists of data. For instance in the Contacts app in iOS the individual contact (where you can add numbers and emails etc...) uses a UITableView to layout the interface.

It takes all of the bother out of having to calculate heights and positions of labels etc...

Define a custom UITableViewCell with the correct layout of one of your UILabels and then you just have to put the right text into the right row.

UITableView is a really powerful tool for things like this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top