提问者:小点点

iOS:自动布局中的多行UILabel


我在尝试用自动布局实现一些非常基本的布局行为时遇到了困难。我的视图控制器在IB中看起来是这样的:

最上面的标签是标题标签,不知道会有多少行。我需要标题标签显示所有的文字行。我还需要另外两个标签和小的图像,以布局的权利下面的标题,但它恰巧是高的。我设置了标签和小图像之间的垂直间距约束,以及标题标签和它的超级视图之间的顶部间距约束和小图像和它的超级视图之间的底部间距约束。白色UIView没有高度限制,因此它应该垂直拉伸以包含其子视图。我已将标题标签的行数设置为0。

如何调整标题标签的大小以适应字符串所需的行数?我的理解是我不能使用setFrame方法,因为我使用的是自动布局。而且我必须使用自动布局,因为我需要那些其他视图留在标题标签下面(因此有约束)。

我怎么才能让这一切发生?


共3个答案

匿名用户

上使用,然后autolayout将处理其余的内容。

[label setPreferredMaxLayoutWidth:200.0];

请参阅PreferredMaxLayOutwidth上的UILabel文档。

更新:

只需要将情节提要中的约束设置为,不需要设置PreferredMaxLayOutwidth。

匿名用户

扩展您的标签,设置行数为0,更重要的是自动布局,设置高度为>=X。自动布局将做剩下的。您也可以根据前一个元素包含其他元素,以便正确定位。

匿名用户

来源:http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html

多行文本的内在内容大小

对于多行文本,UILabel和NSTextField的内在内容大小是不明确的。文本的高度取决于线条的宽度,这还有待于在求解约束条件时确定。为了解决这个问题,两个类都有一个名为preferredMaxLayoutWidth的新属性,它指定了计算内在内容大小的最大线宽。

因为我们通常事先不知道这个值,所以我们需要采取两步走的方法来正确地得到这个值。首先,我们让Auto Layout完成它的工作,然后在Layout pass中使用结果帧更新首选的最大宽度并再次触发Layout。

- (void)layoutSubviews
{
    [super layoutSubviews];
    myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
    [super layoutSubviews];
}

第一次调用[super layoutSubviews]是标签获取其框架集所必需的,而第二次调用是更改后更新布局所必需的。如果省略第二个调用,则会出现NSInternalInconsistencyException错误,因为我们在布局传递中进行了更改,需要更新约束,但我们没有再次触发布局。

我们也可以在label子类本身中这样做:

@implementation MyLabel
- (void)layoutSubviews
{
    self.preferredMaxLayoutWidth = self.frame.size.width;
    [super layoutSubviews];
}
@end

在这种情况下,我们不需要首先调用[super layoutSubviews],因为当调用layoutSubviews时,我们已经在标签本身上有了一个框架。

要从视图控制器级别进行此调整,我们挂钩到ViewDidLayoutSubViews。在这一点上,第一个自动布局的框架已经设置,我们可以使用它们来设置首选的最大宽度。

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

最后,请确保标签上没有显式的高度限制,该限制的优先级高于标签的内容抗压缩优先级。否则它将超过计算出的内容高度。确保检查所有能影响标签高度的约束条件。