我有一个只包含UILabel的视图。此标签包含多行文字。父级具有可变宽度,可以使用平移手势调整大小。我的问题是,当我这样做时,重新调整UILabel不会重新计算其高度,以便所有内容仍然可见,它只是将其切断。
我已经设法通过一些黑客来修复它,但它的运行速度非常慢:
- (void)layoutSubviews {
CGSize labelSize = [self.labelDescription sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];
if (self.constraintHeight) {
[self removeConstraint:self.constraintHeight];
}
self.constraintHeight = [NSLayoutConstraint constraintWithItem:self.labelDescription attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:labelSize.height];
[self addConstraint:self.constraintHeight];
[super layoutSubviews];
}
自动布局不应该自动发生这种情况吗?
修改
我的观点结构是:
UIScrollView
---> UIView
---> UILabel
以下是UIScrollView的约束:
<NSLayoutConstraint:0x120c4860 H:|-(>=32)-[DescriptionView:0x85c81c0] (Names: '|':UIScrollView:0x85db650 )>,
<NSLayoutConstraint:0x120c48a0 H:|-(32@900)-[DescriptionView:0x85c81c0] priority:900 (Names: '|':UIScrollView:0x85db650 )>,
<NSLayoutConstraint:0x120c48e0 H:[DescriptionView:0x85c81c0(<=576)]>,
<NSLayoutConstraint:0x120c4920 H:[DescriptionView:0x85c81c0]-(>=32)-| (Names: '|':UIScrollView:0x85db650 )>,
<NSLayoutConstraint:0x120c4960 H:[DescriptionView:0x85c81c0]-(32@900)-| priority:900 (Names: '|':UIScrollView:0x85db650 )>,
<NSLayoutConstraint:0x8301450 DescriptionView:0x85c81c0.centerX == UIScrollView:0x85db650.centerX>,
以下是对UIView的限制:
<NSLayoutConstraint:0x85c4580 V:|-(0)-[UILabel:0x85bc7b0] (Names: '|':DescriptionView:0x85c81c0 )>,
<NSLayoutConstraint:0x85c45c0 H:|-(0)-[UILabel:0x85bc7b0] (Names: '|':DescriptionView:0x85c81c0 )>,
<NSLayoutConstraint:0x85c9f80 UILabel:0x85bc7b0.trailing == DescriptionView:0x85c81c0.trailing>,
<NSLayoutConstraint:0x85c9fc0 UILabel:0x85bc7b0.centerY == DescriptionView:0x85c81c0.centerY>
UILabel本身没有任何约束,除了将其固定到其父级的边缘
答案 0 :(得分:41)
好的,我终于把它钉了下来。解决方案是在preferredMaxLayoutWidth
中设置viewDidLayoutSubviews
,但在第一轮布局后仅设置。您可以通过异步调度回主线程来安排此操作。所以:
- (void)viewDidLayoutSubviews {
dispatch_async(dispatch_get_main_queue(), ^{
self.theLabel.preferredMaxLayoutWidth = self.theLabel.bounds.size.width;
});
}
这样,在之后 之前,你没有设置preferredMaxLayoutWidth
标签的宽度已被其与superview相关的约束正确设置。
这里的工作示例项目:
编辑:另一种方法!子类UILabel并覆盖layoutSubviews
:
- (void) layoutSubviews {
[super layoutSubviews];
self.preferredMaxLayoutWidth = self.bounds.size.width;
}
结果是一个自尺寸标签 - 无论宽度如何变化(假设其宽度因约束/布局而改变),它都会自动更改其高度以适应其内容。
答案 1 :(得分:26)
我在向Apple提出错误后解决了这个问题。多行文本需要两遍布局的问题,这一切都依赖于属性preferredMaxLayoutWidth
以下是需要添加到包含多行标签的视图控制器的相关代码:
- (void)viewWillLayoutSubviews
{
// Clear the preferred max layout width in case the text of the label is a single line taking less width than what would be taken from the constraints of the left and right edges to the label's superview
[self.label setPreferredMaxLayoutWidth:0.];
}
- (void)viewDidLayoutSubviews
{
// Now that you know what the constraints gave you for the label's width, use that for the preferredMaxLayoutWidth—so you get the correct height for the layout
[self.label setPreferredMaxLayoutWidth:[self.label bounds].size.width];
// And then layout again with the label's correct height.
[self.view layoutSubviews];
}
答案 2 :(得分:4)
在Xcode 6.1 for iOS 7/8中,我只需在我的视图中调用的setter方法中设置preferredMaxLayoutWidth
即可显示标签的文本。我猜它开始时设置为0
。以下示例,其中self.teachPieceLabel
是标签。在Interface Builder的视图中,标签与约束以及其他标签一起连接。
- (void)setTeachPieceText:(NSString *)teachPieceText {
self.teachPieceLabel.text = teachPieceText;
[self.teachPieceLabel setPreferredMaxLayoutWidth:[self.teachPieceLabel bounds].size.width];
}