UILabel sizeToFit不适用于autolayout ios 6

时间:2013-04-15 07:01:07

标签: ios ios6 uilabel autolayout

我应该如何以编程方式(以及在哪种方法中)配置UILabel,其高度取决于其文本?我一直在尝试使用Storyboard和代码的组合进行设置,但无济于事。在设置sizeToFitlineBreakMode时,每个人都建议numberOfLines。但是,无论我将代码放在viewDidLoad:viewDidAppear:还是viewDidLayoutSubviews,我都无法将其付诸实践。我要么让盒子太小而不能长文本也不会长,或者我把它做得太大而且不会缩小。

13 个答案:

答案 0 :(得分:403)

请注意在大多数情况下Matt's solution按预期工作。但如果它不适合你,请进一步阅读。

要使标签自动调整高度,您需要执行以下操作:

  1. 设置标签
  2. 的布局约束
  3. 设置低优先级的高度约束。它应该低于ContentCompressionResistancePriority
  4. 设置numberOfLines = 0
  5. 将ContentHuggingPriority设置为高于标签的高度优先级
  6. 为label设置preferredMaxLayoutWidth。标签使用该值来计算其高度
  7. 例如:

    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

    1. 设置四个约束。高度约束是强制性的。 enter image description here

    2. 然后转到标签的属性检查器并将行数设置为0。 enter image description here

    3. 转到标签尺寸检查器并增加垂直ContentHuggingPriority和垂直ContentCompressionResistancePriority。
      enter image description here

    4. 选择并编辑高度限制 enter image description here

    5. 降低高度约束优先级 enter image description here

    6. <强>享受。 :)

答案 1 :(得分:63)

在iOS 6中,使用autolayout,如果UILabel的边(或宽度)和顶部固定,它将自动垂直增长和缩小以适合其内容,根本没有代码并且没有弄乱它的抗压性或其他什么。这很简单。

在更复杂的情况下,只需设置标签preferredMaxLayoutWidth

无论哪种方式,正确的事情都会自动发生。

答案 2 :(得分:42)

虽然问题以编程方式陈述,遇到了同样的问题,并且更喜欢在Interface Builder中工作,但我认为使用Interface Builder解决方案添加到现有答案可能很有用。

首先要忘记sizeToFit。自动布局将根据内在内容大小代表您处理此问题。

问题是,如何通过自动布局获取标签以适应其内容?具体 - 因为问题提到它 - 身高。请注意,相同的原则适用于宽度。

让我们从一个高度设置为41px高的示例UILabel开始:

enter image description here

正如您在上面的屏幕抓取中看到的那样,"This is my text"上方和下方都有填充。这是在UILabel的高度之间填充,它的内容是文本。

如果我们在模拟器中运行应用程序,果然,我们看到同样的事情:

enter image description here

现在,让我们在Interface Builder中选择UILabel,然后查看尺寸检查器中的默认设置:

enter image description here

请注意上面突出显示的约束。这是内容拥抱优先级。正如Erica Sadun在优秀iOS Auto Layout Demystified中描述的那样,这是:

  

视图更喜欢避免在其核心内容周围添加额外填充的方式

对于我们来说,使用UILabel,核心内容就是文本。

我们来到这个基本场景的核心。我们给了我们的文本标签两个约束。他们发生冲突一个人说“高度必须等于41像素高”。另一个说“拥抱它的内容,所以我们没有任何额外的填充”。在我们的例子中,拥抱视图的文本,所以我们没有任何额外的填充。

现在,使用自动布局,有两个不同的指令表示做不同的事情,运行时必须选择其中一个。它不能两者兼顾。 UILabel不能同时为41像素高,没有填充。

解决此问题的方法是指定优先级。一条指令必须具有比另一条指令更高的优先级。如果两个指令都说不同,并具有相同的优先级,则会发生异常。

所以让我们试一试。我的身高限制优先级为 1000 必需。内容拥抱高度 250 。如果我们将高度约束优先级降低到 249 会怎样?

enter image description here

现在我们可以看到神奇的开始发生。我们试试sim:

enter image description here

真棒!内容拥抱实现。仅因为高度优先级 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)

我觉得我应该做出贡献,因为我花了一些时间才找到正确的解决方案:

  • 目标是让Auto Layout在不调用sizeToFit()的情况下完成工作,我们将通过指定正确的约束来实现:
  • 在UILabel上指定top,bottom和leading / trailing空间约束
  • 将行数属性设置为0
  • 将内容拥抱优先级提高到1000
  • 将内容压缩阻力优先级降低到500
  • 在底部容器约束中,将优先级降低到500

基本上,你告诉你的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;自动并固定标签顶部,前导和尾随enter image description here

答案 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)

对我有用的解决方案;如果您的UILabel具有固定宽度,请在接口文件中将约束从constant =更改为constant <=

enter image description here

答案 12 :(得分:-1)

在我使用UITableViewCell中的标签时,标签at会调整大小,但高度会超出表格单元格高度。这对我有用。我根据Max MacLeod做了,然后确保将单元格高度设置为UITableViewAutomaticDimension。

您可以在init或awakeFromNib中添加它,

self.tableView.rowHeight = UITableViewAutomaticDimension.  

在故事板中,选择单元格,打开“大小”检查器,并通过取消选中“自定义”复选框,确保行高设置为“默认”。

8.0中存在一个问题,也需要在代码中设置它。