Reputation: 173
The code below, I think should result iin a multiline label followed by a button, however, after layout there is only a single line of the label showing up. While I could put an explicit height in the vertical layout that would defeat the purpose. Any ideas about what other constraints I should apply?
UILabel *lbExplain = [[UILabel alloc] init];
lbExplain.text = @"The Sync process allows you to synchronize your library between different devices. By clicking on the button below you can find other devices to sync with. The other device also has to be running this applicaton.";
lbExplain.lineBreakMode = NSLineBreakByWordWrapping;
lbExplain.numberOfLines = 0;
lbExplain.translatesAutoresizingMaskIntoConstraints = NO;
UIButton *btnPartner = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnPartner setTitle:@"Look for Partners" forState:UIControlStateNormal];
[btnPartner addTarget:self action:@selector(findPartners:) forControlEvents:UIControlEventTouchUpInside];
btnPartner.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:lbExplain];
[self.view addSubview:btnPartner];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[lbExplain]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(lbExplain)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[lbExplain]-[btnPartner]" options:NSLayoutFormatAlignAllLeft metrics:nil views:NSDictionaryOfVariableBindings(lbExplain, btnPartner)]];
Upvotes: 17
Views: 13720
Reputation: 1519
I had a similar problem, where a multiline label in a UITableViewCell, positioned with AutoLayout, wouldn't expand itself.
It was inside a UITableView handling sizes 'automatically' with UITableViewAutomaticDimension and estimatedHeightForRowAtIndexPath method. (I think it may be the source of the problem)
I figured out this problem by calling :
[cell layoutIfNeeded]
in the cellForRowAtIndexPath method, just before returning the cell.
And it worked like a charm !
Upvotes: 0
Reputation: 1589
The issue here is that preferredMaxLayoutWidth
is not set. As a result, the text is not constrained by any width and, as such, it does not wrap to the next line.
I've found that the easiest way to use a multiline UILabel
with Autolayout is to create a subclass:
@interface MyMultilineLabel : UILabel
@end
@implementation MyMultilineLabel
- (void)setBounds:(CGRect)bounds {
[super setBounds:bounds];
CGFloat width = CGRectGetWidth(bounds);
if (self.preferredMaxLayoutWidth != width) {
self.preferredMaxLayoutWidth = width;
}
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.lineBreakMode = NSLineBreakByWordWrapping;
self.numberOfLines = 0;
}
return self;
}
@end
Upvotes: 1
Reputation: 104082
Add the line:
lbExplain.preferredMaxLayoutWidth = 280;
This must be something that is done automatically in IB, since the label expands properly if you set it up there. The number you pass it does seem to matter some in how it expands vertically, but it doesn't override the constraints you set for the width.
After Edit:
It works better if I add that line in updateViewConstraints, and relate the number to the view's bounds. This way it adjusts properly on rotation.
-(void)updateViewConstraints {
[super updateViewConstraints];
lbExplain.preferredMaxLayoutWidth = self.view.bounds.size.width - 40;
}
Upvotes: 38
Reputation: 1624
Are you sure that you don't have ambiguous layout ?
you can make a test in your code like
if ([self.view hasAmbiguousLayout]) {
NSLog(@"ambiguous");
}
or make pause on the simulator or test device and type in console :
po [[UIWindow keyWindow] _autolayoutTrace]
if so, you might wanna try to make your contraints a bit more explicit like (at first sight, height is ambiguous):
@"V:|-[lbExplain]-[btnPartner]-|"
or
@"V:|-[lbExplain(==300)]-[btnPartner(==200)]"
here is the documentation to the visual format language :
Upvotes: 0