iOS:自动布局中的多行 UILabel
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12789013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iOS: Multi-line UILabel in Auto Layout
提问by James Harpe
I'm having trouble trying to achieve some very basic layout behavior with Auto Layout. My view controller looks like this in IB:
我在尝试使用自动布局实现一些非常基本的布局行为时遇到了麻烦。我的视图控制器在 IB 中是这样的:
The top label is the title label, I don't know how many lines it will be. I need the title label to display all lines of text. I also need the other two labels and the small image to be laid out right below the title, however tall it happens to be. I have set vertical spacing constraints between the labels and small image, as well as a top spacing constraint between the title label and its superview and a bottom spacing constraint between the small image and its superview. The white UIView has no height constraint, so it should stretch vertically to contain its subviews. I have set the number of lines for the title label to 0.
最上面的标签是标题标签,不知道会有多少行。我需要标题标签来显示所有文本行。我还需要将其他两个标签和小图像放在标题下方,无论它有多高。我在标签和小图像之间设置了垂直间距约束,以及标题标签与其父视图之间的顶部间距约束以及小图像与其父视图之间的底部间距约束。白色的 UIView 没有高度限制,所以它应该垂直拉伸以包含它的子视图。我已将标题标签的行数设置为 0。
How can I get the title label to resize to fit the number of lines required by the string? My understanding is that I can't use setFrame methods because I'm using Auto Layout. And I have to use Auto Layout because I need those other views to stay below the title label (hence the constraints).
如何让标题标签调整大小以适应字符串所需的行数?我的理解是我不能使用 setFrame 方法,因为我使用的是自动布局。而且我必须使用自动布局,因为我需要那些其他视图保持在标题标签下方(因此存在约束)。
How can I make this happen?
我怎样才能做到这一点?
回答by mwhuss
Use -setPreferredMaxLayoutWidth
on the UILabel
and autolayout should handle the rest.
使用-setPreferredMaxLayoutWidth
上UILabel
和自动版式应该处理其余部分。
[label setPreferredMaxLayoutWidth:200.0];
See the UILabel documentation on preferredMaxLayoutWidth.
请参阅有关 preferredMaxLayoutWidth的UILabel 文档。
Update:
更新:
Only need to set the height
constraint in storyboard to Greater than or equal to
, no need to setPreferredMaxLayoutWidth.
只需将height
storyboard中的约束设置为Greater than or equal to
,无需设置PreferredMaxLayoutWidth。
回答by Charlie Wu
Expand your label set number of lines to 0 and also more importantly for auto layout set height to >= x. Auto layout will do the rest. You may also contain your other elements based on previous element to correctly position then.
将您的标签集行数扩展到 0,更重要的是将自动布局设置高度设置为 >= x。自动布局将完成剩下的工作。您还可以包含基于先前元素的其他元素以正确定位。
回答by Anton Matosov
Source: http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
来源:http: //www.objc.io/issue-3/advanced-auto-layout-toolbox.html
Intrinsic Content Size of Multi-Line Text
多行文本的内在内容大小
The intrinsic content size of UILabel and NSTextField is ambiguous for multi-line text. The height of the text depends on the width of the lines, which is yet to be determined when solving the constraints. In order to solve this problem, both classes have a new property called preferredMaxLayoutWidth, which specifies the maximum line width for calculating the intrinsic content size.
UILabel 和 NSTextField 的内在内容大小对于多行文本是不明确的。文本的高度取决于线条的宽度,这在求解约束时尚未确定。为了解决这个问题,这两个类都有一个名为 preferredMaxLayoutWidth 的新属性,它指定了计算内在内容大小的最大线宽。
Since we usually don't know this value in advance, we need to take a two-step approach to get this right. First we let Auto Layout do its work, and then we use the resulting frame in the layout pass to update the preferred maximum width and trigger layout again.
由于我们通常事先不知道这个值,因此我们需要采取两步方法来做到这一点。首先我们让 Auto Layout 做它的工作,然后我们在布局过程中使用结果框架来更新首选的最大宽度并再次触发布局。
- (void)layoutSubviews
{
[super layoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[super layoutSubviews];
}
The first call to [super layoutSubviews] is necessary for the label to get its frame set, while the second call is necessary to update the layout after the change. If we omit the second call we get a NSInternalInconsistencyException error, because we've made changes in the layout pass which require updating the constraints, but we didn't trigger layout again.
第一次调用 [super layoutSubviews] 是标签获取其框架集所必需的,而第二次调用是更改后更新布局所必需的。如果我们省略第二个调用,我们会得到一个 NSInternalInconsistencyException 错误,因为我们已经在需要更新约束的布局过程中进行了更改,但我们没有再次触发布局。
We can also do this in a label subclass itself:
我们也可以在标签子类本身中做到这一点:
@implementation MyLabel
- (void)layoutSubviews
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[super layoutSubviews];
}
@end
In this case, we don't need to call [super layoutSubviews] first, because when layoutSubviews gets called, we already have a frame on the label itself.
在这种情况下,我们不需要先调用 [super layoutSubviews],因为当 layoutSubviews 被调用时,我们已经在标签上有了一个框架。
To make this adjustment from the view controller level, we hook into viewDidLayoutSubviews. At this point the frames of the first Auto Layout pass are already set and we can use them to set the preferred maximum width.
为了从视图控制器级别进行此调整,我们挂钩到 viewDidLayoutSubviews。此时第一个 Auto Layout pass 的 frame 已经设置好了,我们可以使用它们来设置首选的最大宽度。
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
myLabel.preferredMaxLayoutWidth = myLabel.frame.size.width;
[self.view layoutIfNeeded];
}
Lastly, make sure that you don't have an explicit height constraint on the label that has a higher priority than the label's content compression resistance priority. Otherwise it will trump the calculated height of the content. Make sure to check all the constraints that can affect label's height.
最后,确保您没有对优先级高于标签内容压缩阻力优先级的标签设置明确的高度限制。否则它将胜过计算的内容高度。确保检查所有可能影响标签高度的约束。
回答by Cory Imdieke
I was just fighting with this exact scenario, but with quite a few more views that needed to resize and move down as necessary. It was driving me nuts, but I finally figured it out.
我只是在与这个确切的场景作斗争,但是还有更多的视图需要根据需要调整大小和向下移动。这让我发疯,但我终于想通了。
Here's the key: Interface Builder likes to throw in extra constraints as you add and move views and you may not notice. In my case, I had a view half way down that had an extra constraint that specified the size between it and its superview, basically pinning it to that point. That meant that nothing above it could resize larger because it would go against that constraint.
这是关键:Interface Builder 喜欢在您添加和移动视图时加入额外的约束,而您可能不会注意到。在我的例子中,我有一个视图中间有一个额外的约束,指定它和它的超级视图之间的大小,基本上将它固定到那个点。这意味着它上面的任何东西都不能变大,因为它会违反该约束。
An easy way to tell if this is the case is by trying to resize the label manually. Does IB let you grow it? If it does, do the labels below move as you expect? Make sure you have both of these checked before you resize to see how your constraints will move your views:
判断是否属于这种情况的一种简单方法是尝试手动调整标签大小。IB让你成长吗?如果是这样,下面的标签是否按您的预期移动?在调整大小以查看约束将如何移动视图之前,请确保检查了这两项:
If the view is stuck, follow the views that are below it and make sure one of them doesn't have a top space to superview constraint. Then just make sure your number of lines option for the label is set to 0 and it should take care of the rest.
如果视图被卡住,请遵循其下方的视图,并确保其中之一没有超视图约束的顶部空间。然后只需确保您的标签行数选项设置为 0,其余的应该由它来处理。
回答by Chris
I find you need the following:
我发现您需要以下内容:
- A top constraint
- A leading constraint (eg left side)
- A trailing constraint (eg right side)
- Set content hugging priority, horizontal to low, so it'll fill the given space if the text is short.
- Set content compression resistance, horizontal to low, so it'll wrap instead of try to become wider.
- Set the number of lines to 0.
- Set the line break mode to word wrap.
- 顶部约束
- 前导约束(例如左侧)
- 尾随约束(例如右侧)
- 设置内容拥抱优先级,水平为低,因此如果文本很短,它将填充给定的空间。
- 设置内容压缩阻力,水平为低,所以它会环绕而不是尝试变得更宽。
- 将行数设置为 0。
- 将换行模式设置为自动换行。
回答by Tanguy G.
None of the different solutions found in the many topics on the subject worked perfectly for my case (x dynamic multiline labels in dynamic table view cells) .
在有关该主题的许多主题中找到的不同解决方案都不适用于我的情况(动态表视图单元格中的 x 动态多行标签)。
I found a way to do it :
我找到了一种方法:
After having set the constraints on your label and set its multiline property to 0, make a subclass of UILabel ; I called mine AutoLayoutLabel :
在标签上设置约束并将其 multiline 属性设置为 0 后,创建 UILabel 的子类;我打电话给我的 AutoLayoutLabel :
@implementation AutoLayoutLabel
- (void)layoutSubviews{
[self setNeedsUpdateConstraints];
[super layoutSubviews];
self.preferredMaxLayoutWidth = CGRectGetWidth(self.bounds);
}
@end
回答by A.G
I have a UITableViewCell which has a text wrap label. I worked text wrapping as follows.
我有一个带有文本换行标签的 UITableViewCell。我按如下方式进行文本换行。
1) Set UILabel constraints as follows.
1) 如下设置 UILabel 约束。
2) Set no. of lines to 0.
2) 设置编号 行数为 0。
3) Added UILabel height constraint to UITableViewCell.
3) 为 UITableViewCell 添加了 UILabel 高度约束。
@IBOutlet weak var priorityLabelWidth: NSLayoutConstraint!
4) On UITableViewCell:
4) 在 UITableViewCell 上:
priorityLabel.sizeToFit()
priorityLabelWidth.constant = priorityLabel.intrinsicContentSize().width+5
回答by user1662392
One way to do this... As text length increases try to change (decrease) the fontsize of the label text using
一种方法来做到这一点......随着文本长度的增加尝试使用更改(减少)标签文本的字体大小
Label.adjustsFontSizeToFitWidth = YES;