iOS:自动布局中的多行UILabel

我无法通过自动布局来实现一些非常基本的布局行为。 我的视图控制器在IB中看起来像这样:

在这里输入图像描述

最上面的标签是标题标签,我不知道会有多less行。 我需要标题标签来显示文本的所有行。 我还需要另外两个标签和小图片放在标题下方,不pipe高度如何。 我已经设置标签和小图像之间的垂直间距约束,以及标题标签和其超视图之间的顶部间距约束以及小图像和其超视图之间的底部间距约束。 白色的UIView没有高度约束,所以它应该垂直拉伸以包含它的子视图。 我已经将标题标签的行数设置为0。

我怎样才能得到标题标签resize,以适应string所需的行数? 我的理解是,我不能使用setFrame方法,因为我使用自动布局。 而我必须使用自动布局,因为我需要这些其他视图留在标题标签(因此约束)之下。

我怎样才能做到这一点?

UILabel上使用-setPreferredMaxLayoutWidth ,自动布局应该处理剩下的事情。

 [label setPreferredMaxLayoutWidth:200.0]; 

请参阅UILabel文档 。

更新:

只需要将Storyboard中的高度约束设置为“大于等于”,不需要设置PreferredMaxLayoutWidth。

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

自动布局

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

多行文本的固有内容大小

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

由于我们通常不会提前知道这个值,所以我们需要采取两步走的方法来解决这个问题。 首先,我们让自动布局执行工作,然后使用布局过程中的结果帧再次更新首选的最大宽度和触发布局。

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

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

我们也可以在标签子类本身中做到这一点:

 @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]; } 

最后,请确保您的标签具有比标签的内容压缩阻力优先级更高的优先级,但没有明确的高度限制。 否则,它将胜过内容的计算高度。 确保检查所有可能影响标签高度的限制。

我只是在与这个确切的情况作斗争,但还有不less意见需要调整,并在必要时下调。 这让我疯狂,但我终于明白了。

以下是关键:Interface Builder喜欢在添加和移动视图时添加额外的约束,您可能不会注意到。 在我的情况下,我有一个观点,有一个额外的约束,指定它和它的超级视图之间的大小,基本上固定到这一点。 这意味着没有任何东西可以重新调整,因为它会违背这个约束。

判断这种情况的简单方法是尝试手动调整标签的大小。 IB让你成长吗? 如果是这样,下面的标签是否按照您的预期移动? 请确保在resize之前检查了这两个选项,以查看约束条件如何移动您的视图:

IB菜单

如果视图卡住了,请按照下面的视图来确保其中一个没有顶部空间来查看约束。 然后,只要确保标签的行数选项设置为0,则应该照顾其余部分。

我觉得你需要以下几点:

  • 顶级约束
  • 领先的约束(例如左侧)
  • 尾随约束(例如右侧)
  • 设置内容拥有优先级,从水平到低,所以如果文本短,它将填充给定的空间。
  • 设置内容压缩阻力,从水平到低,所以它将包裹而不是尝试变宽。
  • 将行数设置为0。
  • 将换行符模式设置为换行。

在这个主题的许多主题中find的不同解决scheme都不能很好地适用于我的情况(dynamic表视图单元格中的xdynamic多行标签)。

我find了一个方法来做到这一点:

在您的标签上设置约束并将其多行属性设置为0之后,创buildUILabel的子类; 我打电话给我的AutoLayoutLabel:

 @implementation AutoLayoutLabel - (void)layoutSubviews{ [self setNeedsUpdateConstraints]; [super layoutSubviews]; self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds); } @end 

我有一个文本换行标签的UITableViewCell。 我工作文本包装如下。

1)设置UILabel约束如下。

在这里输入图像描述

2)设置号码。 的行数为0。

3)将UILabel高度约束添加到UITableViewCell。

 @IBOutlet weak var priorityLabelWidth: NSLayoutConstraint! 

4)在UITableViewCell上:

 priorityLabel.sizeToFit() priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5 

一种方法做到这一点…随着文本的长度增加尝试改变(减less)使用的标签文本的字体大小

 Label.adjustsFontSizeToFitWidth = YES;