我应该如何以编程方式(以及在哪种方法中)配置UILabel,其高度取决于其文本?我一直在尝试使用Storyboard和代码的组合进行设置,但无济于事。在设置sizeToFit
和lineBreakMode
时,每个人都建议numberOfLines
。但是,无论我将代码放在viewDidLoad:
,viewDidAppear:
还是viewDidLayoutSubviews
,我都无法将其付诸实践。我要么让盒子太小而不能长文本也不会长,或者我把它做得太大而且不会缩小。
答案 0 :(得分:403)
请注意在大多数情况下Matt's solution按预期工作。但如果它不适合你,请进一步阅读。
要使标签自动调整高度,您需要执行以下操作:
例如:
self.descriptionLabel = [[UILabel alloc] init];
self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.descriptionLabel.preferredMaxLayoutWidth = 200;
[self.descriptionLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.descriptionLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:self.descriptionLabel];
NSArray* constrs = [NSLayoutConstraint constraintsWithVisualFormat:@"|-8-[descriptionLabel_]-8-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)];
[self addConstraints:constrs];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[descriptionLabel_]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
[self.descriptionLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[descriptionLabel_(220@300)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];
使用Interface Builder
设置四个约束。高度约束是强制性的。
然后转到标签的属性检查器并将行数设置为0。
转到标签尺寸检查器并增加垂直ContentHuggingPriority和垂直ContentCompressionResistancePriority。
选择并编辑高度限制
降低高度约束优先级
<强>享受。 :)强>
答案 1 :(得分:63)
在iOS 6中,使用autolayout,如果UILabel的边(或宽度)和顶部固定,它将自动垂直增长和缩小以适合其内容,根本没有代码并且没有弄乱它的抗压性或其他什么。这很简单。
在更复杂的情况下,只需设置标签preferredMaxLayoutWidth
。
无论哪种方式,正确的事情都会自动发生。
答案 2 :(得分:42)
虽然问题以编程方式陈述,遇到了同样的问题,并且更喜欢在Interface Builder中工作,但我认为使用Interface Builder解决方案添加到现有答案可能很有用。
首先要忘记sizeToFit
。自动布局将根据内在内容大小代表您处理此问题。
问题是,如何通过自动布局获取标签以适应其内容?具体 - 因为问题提到它 - 身高。请注意,相同的原则适用于宽度。
让我们从一个高度设置为41px高的示例UILabel开始:
正如您在上面的屏幕抓取中看到的那样,"This is my text"
上方和下方都有填充。这是在UILabel的高度之间填充,它的内容是文本。
如果我们在模拟器中运行应用程序,果然,我们看到同样的事情:
现在,让我们在Interface Builder中选择UILabel,然后查看尺寸检查器中的默认设置:
请注意上面突出显示的约束。这是内容拥抱优先级。正如Erica Sadun在优秀iOS Auto Layout Demystified中描述的那样,这是:
视图更喜欢避免在其核心内容周围添加额外填充的方式
对于我们来说,使用UILabel,核心内容就是文本。
我们来到这个基本场景的核心。我们给了我们的文本标签两个约束。他们发生冲突一个人说“高度必须等于41像素高”。另一个说“拥抱它的内容,所以我们没有任何额外的填充”。在我们的例子中,拥抱视图的文本,所以我们没有任何额外的填充。
现在,使用自动布局,有两个不同的指令表示做不同的事情,运行时必须选择其中一个。它不能两者兼顾。 UILabel不能同时为41像素高,和没有填充。
解决此问题的方法是指定优先级。一条指令必须具有比另一条指令更高的优先级。如果两个指令都说不同,并具有相同的优先级,则会发生异常。
所以让我们试一试。我的身高限制优先级为 1000 ,必需。内容拥抱高度 250 ,弱。如果我们将高度约束优先级降低到 249 会怎样?
现在我们可以看到神奇的开始发生。我们试试sim:
真棒!内容拥抱实现。仅因为高度优先级 249 小于内容拥抱优先级 250 。基本上,我说“我在这里指定的高度不如我为内容拥抱指定的那么重要”。所以,内容拥抱赢了。
底线,使标签适合文本可以像指定高度 - 或宽度 - 约束一样简单,并正确设置与该轴'内容拥抱优先级约束相关联的优先级。< / em>
将为读者留下相当于宽度的练习!
答案 3 :(得分:7)
在IOS7中注意到sizeToFit也不起作用 - 或许这个解决方案也可以帮到你
[textView sizeToFit];
[textView layoutIfNeeded];
答案 4 :(得分:4)
确保标签的preferredMaxLayoutWidth的另一个选项与标签的宽度保持同步:
#import "MyLabel.h"
@implementation MyLabel
-(void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
// This appears to be needed for iOS 6 which doesn't seem to keep
// label preferredMaxLayoutWidth in sync with its width, which
// means the label won't grow vertically to encompass its text if
// the label's width constraint changes.
self.preferredMaxLayoutWidth = self.bounds.size.width;
}
@end
答案 5 :(得分:4)
我觉得我应该做出贡献,因为我花了一些时间才找到正确的解决方案:
基本上,你告诉你的UILabel虽然它有一个固定的高度约束,它可以打破约束使自己变小以拥抱内容(例如,如果你有一行),但它不能打破限制,使其变大。
答案 6 :(得分:3)
在我的情况下,我创建了一个包含UILabel(长度未知)的UIView子类。在iOS7中,代码很简单:设置约束,不要担心内容拥抱或压缩阻力,一切都按预期工作。
但是在iOS6中,UILabel总是被剪裁成一行。以上答案都不适合我。内容拥抱和压缩阻力设置被忽略。阻止剪切的唯一解决方案是在标签上包含preferredMaxLayoutWidth。但我不知道将首选宽度设置为什么,因为其父视图的大小未知(实际上,它将由内容定义)。
我终于找到了解决方案here。因为我正在处理自定义视图,所以我可以在计算约束一次后添加以下方法来设置首选布局宽度,然后重新计算它们:
- (void)layoutSubviews
{
// Autolayout hack required for iOS6
[super layoutSubviews];
self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width;
[super layoutSubviews];
}
答案 7 :(得分:2)
我已经解决了xCode6 put&#34; Preferred Width&#34;自动并固定标签顶部,前导和尾随
答案 8 :(得分:2)
我以编程方式添加了UILabel
,在我的情况下就足够了:
label.translatesAutoresizingMaskIntoConstraints = false
label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
label.numberOfLines = 0
答案 9 :(得分:0)
UIFont *customFont = myLabel.font;
CGSize size = [trackerStr sizeWithFont:customFont
constrainedToSize:myLabel.frame.size // the size here should be the maximum size you want give to the label
lineBreakMode:UILineBreakModeWordWrap];
float numberOfLines = size.height / customFont.lineHeight;
myLabel.numberOfLines = numberOfLines;
myLabel.frame = CGRectMake(258, 18, 224, (numberOfLines * customFont.lineHeight));
答案 10 :(得分:0)
我遇到了这个问题,还有一个UIView子类,如果它的内部元素包含一个UILabel。即使使用自动布局并尝试所有推荐的解决方案,标签也不会将其高度收紧到文本。就我而言,我只希望标签是一行。
无论如何,对我来说有用的是为UILabel添加一个必需的高度约束,并在调用intrinsicContentSize时手动将其设置为正确的高度。如果你没有UILabel包含在另一个UIView中,你可以尝试继承UILabel并提供类似的实现,首先设置高度约束,然后返回
[super instrinsicContentSize]; 而不是[self.containerview intrinsiceContentSize];就像我在下面做的那样,特定于我的UIView子类。
- (CGSize)intrinsicContentSize
{
CGRect expectedTextBounds = [self.titleLabel textRectForBounds:self.titleLabel.bounds limitedToNumberOfLines:1];
self.titleLabelHeightConstraint.constant = expectedTextBounds.size.height;
return [self.containerView intrinsicContentSize];
}
现在可以在iOS 7和iOS 8上完美运行。
答案 11 :(得分:0)
答案 12 :(得分:-1)
在我使用UITableViewCell中的标签时,标签at会调整大小,但高度会超出表格单元格高度。这对我有用。我根据Max MacLeod做了,然后确保将单元格高度设置为UITableViewAutomaticDimension。
您可以在init或awakeFromNib中添加它,
self.tableView.rowHeight = UITableViewAutomaticDimension.
在故事板中,选择单元格,打开“大小”检查器,并通过取消选中“自定义”复选框,确保行高设置为“默认”。
8.0中存在一个问题,也需要在代码中设置它。