5

I'm trying to programmatically create a container view with two UILabel subviews which behave as follows:

  • The container width is pinned to its superview; its height is constrained to fit the labels
  • The labels are laid out horizontally, with standard spacing between them (8pts)
  • The left label width is 25% of the width of the container
  • The right label width fills the available space, minus standard horizontal spacing
  • Long text should be broken at word boundaries are flow across multiple lines; both labels must grow vertically to accommodate long text

I have defined the labels with numberOfLines = 0 and lineBreakMode = NSLineBreakByWordWrapping.

Note that the size of the container is completely dynamic; its width is determined by its superview, while its height is determined by its subviews (the labels). The size of the labels is also dynamic; their widths are proportional to the container width, and their heights depend on the length of the text.

I've been able to achieve everything above, except for the last item, with the following constraints (pseudo-code). A is the left label, B is the right.

  • A.top == container.top
  • B.top == container.top
  • A.leading = container.leading
  • A.trailing == B.leading - 8
  • B.trailing == container.trailing
  • A == .25 * container.width
  • container.height >= A.height
  • container.height >= B.height

The last 2 constraints are intended to stretch the container to fit the taller of the labels, but the layout engine seems to ignore the fact that the labels may be multiline. That is, I always get a single line displayed, no matter the length of the text.

So what constraints do I need to add/modify/delete in order to achieve the full set of behaviors described above?

lencharest
  • 2,825
  • 2
  • 15
  • 22
  • I would suggest making a really simple one-view demo project with this defined in it, and post it to Dropbox (or equiv). If you can get some points a bounty of 50 really gets a lot of attention here too. Two ideas to throw out - you can ask the label to resize given its current contents (or ask it for the size that is needed), you can tell the autolayout system to re-layout, and if you implement the text delegates you will know when the text changes. I have no experience with autolayout today, but am reading up on it actively. – David H Dec 05 '12 at 00:22
  • I'm developing in MonoTouch. I don't think a C# demo would be helpful to the majority of autolayout gurus out there. :-( – lencharest Dec 05 '12 at 18:02

3 Answers3

8

To make your labels automatically resize height you need to do following:

  1. Set layout constrains for label (That what you actually have done)
  2. Set height constraint with low priority. It should be lover than ContentCompressionResistancePriority
  3. Set numberOfLines = 0
  4. Set ContentHuggingPriority higher than label's hight priority
  5. Set preferredMaxLayoutWidth for label. That value is used by label to calculate its height

For example:

self.descriptionLabel = [[[UILabel alloc] init] autorelease];
self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.descriptionLabel.preferredMaxLayoutWidth = 200;

[self.descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.descriptionLabel];

NSArray* constrs = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[descriptionLabel_]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)];
[self addConstraints:constrs];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[descriptionLabel_]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
[self.descriptionLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[descriptionLabel_(220@300)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
Mark Kryzhanouski
  • 7,251
  • 2
  • 22
  • 22
0

Set the priority of Height Constraints for the labels to low value and try setting the constraints in code.

Sandeep Ankam
  • 306
  • 2
  • 7
  • I am already doing everything in code. And priority is not an issue; the existing set of constraints is satisfiable. – lencharest Dec 05 '12 at 18:01
0

Make sure you set

  1. horizontal and vertical content compression resistance priority. If you do not want label to truncate its content then set it to 1000.i.e. required.
  2. Content hugging priority. Look at this answer to understand how it works.
Community
  • 1
  • 1
Geek
  • 8,280
  • 17
  • 73
  • 137