如何根据 UILabel 的内容自动更改 UILabel 对象的高度和下方其他元素的位置,并启用自动布局

How to automatically change height of UILabel object and position of other elements below, based on the content of UILabel, with autolayout enabled

我找到了一些与此主题相关的答案,但没有一个对我有用。我试过 setPreferredMaxLayoutWidth:,将行数设置为 0,设置高度限制 到 XYZ,或等于或大于 XYZ...以及许多不同组合中的所有这些。可能有什么问题?有什么想法吗?

所选标签是需要根据内容更改高度的标签。如果标签包含不适合 1 行的内容,则其下方的标签以及下方可能的其他元素应向下移动。 IB 没有报告约束问题。

如果您在代码中使用自动布局,则设置框架不起作用。您必须创建所需布局所需的约束集。对于这种情况,您需要为 UILabel 添加高度限制。

此处提供有关操作方法的完整教程:http://www.thinkandbuild.it/learn-to-love-auto-layout-programmatically/

如果您想尝试在代码中处理它,那么您可以像这样处理它。我已经布置了一些类似于你所拥有的东西,然后在 5 秒后它将交换一个新的垂直约束以使其中一个标签更高。希望它能引导您朝着正确的方向前进……或者至少是一个方向!

NSArray * vertConstraint;

UIImageView * imageView = [[UIImageView alloc] init];
UILabel * labelOne = [[UILabel alloc] init];
UILabel * labelTwo = [[UILabel alloc] init];
UILabel * labelThree = [[UILabel alloc] init];

imageView.backgroundColor = [UIColor grayColor];
labelOne.backgroundColor = [UIColor redColor];
labelTwo.backgroundColor = [UIColor blueColor];
labelThree.backgroundColor = [UIColor orangeColor];

[imageView setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelOne setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelTwo setTranslatesAutoresizingMaskIntoConstraints: NO];
[labelThree setTranslatesAutoresizingMaskIntoConstraints: NO];

[self.view addSubview:imageView];
[self.view addSubview:labelOne];
[self.view addSubview:labelTwo];
[self.view addSubview:labelThree];

id topGuide = self.topLayoutGuide;
id bottomGuide = self.bottomLayoutGuide;

NSDictionary * viewsDictionary = NSDictionaryOfVariableBindings(imageView, labelOne,labelTwo,labelThree,topGuide, bottomGuide);

// initial vertical constraints.  will be swapped out after 5 seconds (See below
vertConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topGuide]-100-[imageView(==200)]-20-[labelOne(==20)]-20-[labelTwo(==20)]-20-[labelThree(==20)]-(>=5)-[bottomGuide]|" options:0 metrics: 0 views:viewsDictionary];

[self.view addConstraints:vertConstraint];

// horizontal constraints for all the elements
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[imageView(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelOne(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelTwo(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(>=0)-[labelThree(==200)]-(>=0)-|" options:0 metrics: 0 views:viewsDictionary]];

//additional constraints to center them    
[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:imageView
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelOne
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];


[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelTwo
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

[self.view addConstraint:
 [NSLayoutConstraint constraintWithItem:labelThree
                              attribute:NSLayoutAttributeCenterX
                              relatedBy:NSLayoutRelationEqual
                                 toItem:self.view
                              attribute:NSLayoutAttributeCenterX
                             multiplier:1
                               constant:0]];

//delay 5 seconds then swap out vertical constraints
// in this case change the (==20) to (==40) for height of element
// you can edit that string more dynamically to fit your needs
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

    NSArray * newVertConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topGuide]-100-[imageView(==200)]-20-[labelOne(==20)]-20-[labelTwo(==40)]-20-[labelThree(==20)]-(>=5)-[bottomGuide]|" options:0 metrics: 0 views:viewsDictionary];

    [self.view removeConstraints:vertConstraint];
    [self.view addConstraints:newVertConstraint];
    [self.view setNeedsUpdateConstraints];
    [UIView animateWithDuration:1.5 animations:^{
        [self.view layoutIfNeeded];
    }];


});

这是我刚刚成功完成的方法:

  1. 我将标签上的 numberOfLines 设置为 0,因此它会根据需要增大和缩小。
  2. 我给标签 >= 0 左右 leading/trailing space 限制了容器的边距,所以它可以增长到最大宽度。
  3. 没有在标签上设置任何高度限制。因此,高度将由内容决定。
  4. 我确保标签下方的任何垂直约束都不会限制其向下增长。

特别要记住,如果您设置从任何内容到屏幕底部的约束,您需要确保其优先级(或标签链中另一个垂直约束的优先级到底部)设置为比标签的垂直 Content Compression Resistance Priority 更低的优先级。这将确保标签内容的增长可以克服其他垂直限制。