UILabel sizeToFit不适用于自动布局ios6
我该如何以编程方式(以及在哪种方法中)configuration高度取决于文本的UILabel? 我一直在尝试使用Storyboard和代码的组合来设置它,但无济于事。 大家在设置lineBreakMode
和numberOfLines
时候推荐sizeToFit
。 但是,无论我把代码放在viewDidLoad:
, viewDidAppear:
或viewDidLayoutSubviews
我都无法使它工作。 要么我把这个盒子放得太长,不能长长的文字,要么我把它做得太大,不能缩小。
请注意 ,在大多数情况下, Matt的解决scheme按预期工作。 但如果它不适合你,请进一步阅读。
要使标签自动调整高度,您需要执行以下操作:
- 为标签设置布局限制
- 设置低优先级的高度限制。 它应该低于ContentCompressionResistancePriority
- 设置numberOfLines = 0
- 将ContentHuggingPriority设置为高于标签的高度优先级
- 为标签设置preferredMaxLayoutWidth。 该值由标签用来计算其高度
例如:
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。
-
select并编辑高度限制。
-
并降低身高限制优先。
请享用。 🙂
在iOS 6中,如果使用自动布局,如果UILabel的边(或宽度)和顶部被固定,它将自动垂直增长和缩小,以适应其内容, 根本没有代码,也不会干扰其抗压性等等。 这是死的简单。
在更复杂的情况下,只需设置标签的preferredMaxLayoutWidth
。
无论哪种方式,正确的事情自动发生。
虽然这个问题以编程的方式陈述,遇到同样的问题,并且喜欢在Interface Builder中工作,但我认为用Interface Builder解决scheme添加到现有答案可能会有帮助。
首先是忘记sizeToFit
。 自动布局将根据您的内在内容大小代表您处理此问题。
因此,问题是如何获得一个标签来适应自动布局的内容? 具体来说 – 因为这个问题提到它 – 高度。 请注意,相同的原则适用于宽度。
所以,让我们从一个高度设置为41px的示例UILabel开始:
正如你在上面的屏幕截图中看到的, "This is my text"
在上面和下面都有填充。 这是UILabel的高度,它是内容,文本之间的填充。
如果我们在模拟器中运行应用程序,那么我们看到的是同样的事情:
现在,让我们在界面生成器中selectUILabel,并查看“大小”检查器中的默认设置:
注意上面突出显示的约束。 这是内容拥抱优先 。 正如Erica Sadun在优秀的iOS Auto Layout Demystified中所描述的 ,这是:
视图倾向于避免对其核心内容进行额外的填充
对于我们来说,用UILabel,核心内容就是文字。
在这里,我们来谈谈这个基本情景的核心。 我们给了我们的文本标签两个约束。 他们冲突。 一个说“高度必须等于41个像素高” 。 另一个说“拥抱观点的内容,所以我们没有任何额外的填充” 。 在我们的例子中,拥抱它的文本视图,所以我们没有任何额外的填充。
现在,使用自动布局,有两个不同的指令说不同的事情,运行时必须select一个或另一个。 它不能做到这一点。 UILabel不能同时为41个像素, 并且没有填充。
解决这个问题的方法是指定优先级。 一条指令的优先级高于另一条。 如果两个指令说了不同的东西,并且具有相同的优先级,则会发生exception。
所以让我们一起去吧。 我的身高限制优先级为1000 ,这是必需的 。 内容拥抱高度是250 ,这是弱的 。 如果我们将高度限制优先级降低到249,会发生什么?
现在我们可以看到神奇的开始发生。 让我们来试试sim:
真棒! 内容拥抱实现。 仅仅因为身高优先级249小于拥抱优先级250的内容。 基本上,我说的是“我在这里指定的高度并不比我为内容拥抱指定的高度重要” 。 所以,内容拥抱胜。
底线,获得标签以适应文本可以像指定高度或宽度约束一样简单,并正确设置与该轴的内容拥抱优先级约束相关的优先级。
对于读者来说,将宽度作为一个练习来做!
在iOS7 sizetoFit注意到也没有工作 – 也许该解决scheme可能也帮助你
[textView sizeToFit]; [textView layoutIfNeeded];
确保标签的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
我觉得我应该为之付出一些时间来find正确的解决scheme:
- 我们的目标是让Auto Layout在不调用sizeToFit()的情况下完成工作,我们将通过指定正确的约束来做到这一点:
- 指定UILabel上的顶部,底部和前导/尾部空间约束
- 将行数属性设置为0
- 内容拥抱优先级增加到1000
- 将内容压缩阻力优先级降低到500
- 在您的底部容器约束上,将优先级降低到500
基本上,发生的事情是,你告诉你的UILabel,即使它有一个固定的高度约束,它可以打破约束,使自己更小,以拥抱内容(例如,如果你有一个单一的行),但它不能打破约束,使其更大。
在我的情况下,我创build了一个包含UILabel(未知长度)的UIView子类。 在iOS7中,代码很简单:设置约束,不要担心内容拥抱或压缩阻力,一切按预期工作。
但是在iOS6中,UILabel总是被剪裁到一条线上。 上面的答案都没有为我工作。 内容拥抱和压缩阻力设置被忽略。 防止裁剪的唯一解决scheme是在标签上包含preferredMaxLayoutWidth。 但是我不知道如何设置首选宽度,因为它的父视图的大小是未知的(的确,它将由内容定义)。
我终于在这里find了解决办法。 因为我正在处理一个自定义视图,所以我可以添加下面的方法来设置约束计算一次之后的首选布局宽度,然后重新计算它们:
- (void)layoutSubviews { // Autolayout hack required for iOS6 [super layoutSubviews]; self.bodyLabel.preferredMaxLayoutWidth = self.bodyLabel.frame.size.width; [super layoutSubviews]; }
我已经解决了与xCode6把“首选宽度”自动,并钉住标签的顶部,领先和尾随
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。 即使有自动布局和尝试所有推荐的解决scheme,标签也不会收紧文本的高度。 就我而言,我只希望标签是一行。
无论如何,我的工作是为UILabel添加所需的高度约束,并在调用intrinsicContentSize时手动将其设置为正确的高度。 如果你没有包含在另一个UIView中的UILabel,你可以尝试子类化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上完美工作。
我以编程方式添加了UILabel
,在我的情况下就足够了:
label.translatesAutoresizingMaskIntoConstraints = false label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical) label.numberOfLines = 0
一个解决scheme,为我工作; 如果你的UILabel有一个固定的宽度,在你的接口文件中将约束从constant =
改为constant <=
在我使用UITableViewCell中的标签的情况下,标签at会resize,但高度会超出表格单元高度。 这是为我工作。 我根据Max MacLeod做了,然后确定单元格高度设置为UITableViewAutomaticDimension。
你可以添加这个在你的init或awakeFromNib中,
self.tableView.rowHeight = UITableViewAutomaticDimension.
在故事板中,select单元格,打开“大小”检查器,并通过选中“自定义”checkbox确保将行高设置为“默认”。
8.0中有一个问题,也需要在代码中设置。