Answers:
请注意,在大多数情况下,Matt的解决方案可以按预期工作。但是,如果对您不起作用,请进一步阅读。
要使标签自动调整高度,您需要执行以下操作:
例如:
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_)]];
使用界面生成器
设置四个约束。高度限制是强制性的。
然后转到标签的属性检查器,并将行数设置为0。
转到标签的大小检查器,并增加垂直ContentHuggingPriority和垂直ContentCompressionResistancePriority。
选择并编辑高度约束。
并降低高度约束优先级。
请享用。:)
preferredMaxLayoutWidth
或固定标签的宽度(或其右侧和左侧)。就这样!然后,它将自动垂直增大和缩小以适合其内容。
在iOS 6中,使用自动布局,如果将UILabel的侧面(或宽度)和顶部固定,则它会自动垂直增大和缩小以适合其内容,而无需编写任何代码,也不会破坏其抗压强度或其他任何特性。这很简单。
在更复杂的情况下,只需设置标签的preferredMaxLayoutWidth
。
无论哪种方式,正确的事情都会自动发生。
label.sizeToFit()
尽管问题是通过编程方式提出的,也遇到过相同的问题,并且希望在Interface Builder中工作,但我认为使用Interface Builder解决方案添加到现有答案中可能会很有用。
第一件事就是忘记sizeToFit
。自动版式将根据内部内容的大小代表您处理此问题。
因此,问题是,如何使用自动版式获取标签以使其内容适合?具体来说-因为问题提到了-身高。注意,相同的原理也适用于宽度。
因此,让我们从一个UILabel示例开始,该示例的高度设置为41px高:
如您在上方屏幕抓取中所见,在"This is my text"
上方和下方都有填充。那就是在UILabel的高度及其内容(即文本)之间填充。
如果我们确实在模拟器中运行该应用程序,那么肯定会看到相同的内容:
现在,让我们在Interface Builder中选择UILabel,然后查看Size检查器中的默认设置:
请注意上面突出显示的约束。那就是内容拥抱优先。正如Erica Sadun在出色的iOS Auto Layout Demystified中所描述的那样,它是:
视图倾向于避免在其核心内容周围进行额外填充的方式
对于我们来说,使用UILabel,核心内容是文本。
在这里,我们介绍了此基本方案的核心。我们给了文本标签两个约束。他们发生冲突。有人说“高度必须等于41像素高”。另一个说“拥抱它的内容,这样我们就没有多余的填充了”。在我们的例子中,将视图拥抱为其文本,因此我们没有任何多余的填充。
现在,使用自动版式时,两条不同的指令说要做不同的事情,运行时必须选择一个或另一个。它不能同时做到。所述的UILabel不能同时为41个像素高,并且具有没有填充。
解决此问题的方法是指定优先级。一个指令必须具有比另一指令更高的优先级。如果两个指令说的东西不同,并且具有相同的优先级,则将发生异常。
因此,让我们开始吧。我的身高约束的优先级为1000,这是必需的。内容拥抱高度为250,较弱。如果将高度限制优先级降低到249,会发生什么?
现在我们可以看到魔术开始发生了。让我们尝试在SIM卡中:
太棒了!实现了内容拥抱。仅因为高度优先级249小于包含优先级250的内容。基本上,我是说“我在此处指定的高度比为内容拥抱指定的高度重要”。因此,内容拥抱必胜。
底线,使标签适合文本可以很简单,只需指定高度-或宽度-约束,然后将优先级与该轴包含优先级约束的内容相关联地正确设置即可。
留给读者做相当于宽度的练习!
确保标签的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
就我而言,我正在创建一个包含UILabel(长度未知)的UIView子类。在iOS7中,代码简单明了:设置约束,不必担心内容拥挤或抗压缩性,一切都按预期进行。
但是在iOS6中,UILabel始终被剪切为一行。上面的答案都不适合我。内容拥抱和抗压缩性设置被忽略。防止裁剪的唯一解决方案是在标签上包含preferredMaxLayoutWidth。但是我不知道将首选宽度设置为什么,因为其父视图的大小是未知的(实际上,它将由内容定义)。
我终于在这里找到了解决方案。因为我正在使用自定义视图,所以可以只添加以下方法来设置约束一次,然后计算约束,然后设置首选的布局宽度:
- (void)layoutSubviews
{
// Autolayout hack required for iOS6
[super layoutSubviews];
self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width;
[super layoutSubviews];
}
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));
我也遇到了一个UIView子类(如果包含UILabel作为其内部元素)也遇到了这个问题。即使使用自动布局并尝试所有推荐的解决方案,标签也不会将其高度紧贴文本。就我而言,我只希望标签为一行。
无论如何,对我有用的是为UILabel添加所需的高度约束,并在调用internalContentSize时将其手动设置为正确的高度。如果另一个UIView中没有包含UILabel,则可以尝试对UILabel进行子类化,并通过首先设置高度限制然后返回
[super instrinsicContentSize]来提供类似的实现;而不是[self.containerview internaleContentSize]; 就像我在下面做的,这是针对我的UIView sublass的。
- (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上完美运行。
intrinsicContentSize
。运行时应该能够基于正确的设置约束条件来计算此值。
在我的情况下,当在UITableViewCell中使用标签时,标签处的大小会重新调整,但高度会超出表格单元格的高度。这对我有用。我根据Max MacLeod进行了操作,然后确保将单元格高度设置为UITableViewAutomaticDimension。
您可以在init或awakeFromNib中添加它,
self.tableView.rowHeight = UITableViewAutomaticDimension.
在情节提要中,选择单元格,打开“大小”检查器,并通过选中“自定义”复选框确保行高设置为“默认”。
8.0中存在一个问题,该问题也要求在代码中进行设置。
label.sizeToFit()
在Xcode / viewController中使用,约束就足够了。没有在Playground中创建标签。到目前为止,我发现它只能在Playground中使用的唯一方法是label.sizeToFit()