autolayout sizetofit作用 - UILabel sizeToFit不适用于自动布局ios6




width uibutton (12)

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

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

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

所以,让我们从高度设置为41px的示例UILabel开始:

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

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

现在,让我们在界面生成器中选择UILabel,并查看“大小”检查器中的默认设置:

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

视图倾向于避免对其核心内容进行额外填充

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

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

现在,使用Auto Layout,有两个不同的指令说明做不同的事情,运行时必须选择一个或另一个。 它不能做到这一点。 UILabel不能同时高41个像素, 并且没有填充。

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

所以让我们一起去吧。 我的身高限制优先级为1000 ,这是必需的 。 内容拥抱高度是250 ,这是微弱的 。 如果我们将身高限制优先级降至249,会发生什么情况?

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

真棒! 内容拥抱取得成功。 仅仅因为身高优先级249小于拥抱优先级250的内容。 基本上,我说“我在这里指定的高度并不比我为内容拥抱指定的高度重要” 。 所以,内容拥抱赢了。

底线,让标签适合文本可以像指定高度或宽度约束一样简单,并正确设置与该轴的内容拥抱优先级约束关联的优先级。

作为读者的练习,会留下宽度的等效物!

我该如何以编程方式(以及在哪种方法中)配置高度取决于文本的UILabel? 我一直试图使用Storyboard和代码的组合来设置它,但无济于事。 大家在设置lineBreakModenumberOfLines推荐sizeToFit 。 但是,无论我将该代码放在viewDidLoad:viewDidAppear:viewDidLayoutSubviews我都无法使其工作。 要么我把这个盒子放得太小,不能长长的文字,要么我把它做得太大,不缩小。


在IOS7 sizetoFit注意到也没有工作 - 也许该解决方案可能也会帮助你

[textView sizeToFit];
[textView layoutIfNeeded];

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

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

基本上,发生的事情是,你告诉你的UILabel,即使它有一个固定的高度约束,它可以使得为了拥抱内容而缩小它自身的约束(例如,如果你只有一行),但它不能打破约束使其更大。


在iOS 6中,如果使用自动布局,如果UILabel的侧面(或宽度)和顶部被固定,它将自动增长和缩小以适应其内容, 完全没有代码,也不会影响其抗压性等等。 它很简单。

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

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


我以编程方式添加了UILabel ,在我的情况下,这足够了:

label.translatesAutoresizingMaskIntoConstraints = false
label.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
label.numberOfLines = 0

我已经用xCode6解决了将“首选宽度”设置为自动并将标签顶部,顶部和尾部固定


我碰到这个问题以及UIView子类,如果其内部元素包含一个UILabel作为一个。 即使使用自动布局并尝试所有推荐的解决方案,标签也不会收紧文本的高度。 就我而言,我只希望标签是一行。

无论如何,对我而言,工作是为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有一个固定的宽度,在你的界面文件中将约束从constant =改为constant <=


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));

请注意 ,在大多数情况下, Matt的解决方案按预期工作。 但如果它不适合你,请进一步阅读。

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

  1. 为标签设置布局约束
  2. 设置低优先级的高度限制。 它应该低于ContentCompressionResistancePriority
  3. 设置numberOfLines = 0
  4. 将ContentHuggingPriority设置为高于标签的高度优先级
  5. 为标签设置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_([email protected])]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(descriptionLabel_)]];

使用Interface Builder

  1. 设置四个约束。 高度限制是强制性的。

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

  3. 转到标签的大小检查器,并增加垂直ContentHuggingPriority和垂直ContentCompressionResistancePriority。

  4. 选择并编辑高度限制。

  5. 并降低身高限制优先。

请享用。 :)


在我的情况下,我创建了一个包含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];
}

我遇到了同样的问题,看起来可能是因为在设备上启用了开发。

Apple开发论坛上,我发帖询问了我的问题( 我的帖子 ),有人正确地提醒我,许多开发人员一直在抱怨开发设备迟缓。

所以我去了Organizer并从那里忽略了我的设备,在启用开发时将其删除。 我重新启动了设备,确定我的MKMapView非常快捷。 它有时仍然低迷,但性能显着提高。

试试你的设备,看看你是否注意到了差异。







ios ios6 uilabel autolayout