可可自动版式:内容拥抱与内容压缩抗性优先


643

我在Apple文档中找不到关于Cocoa Autolayout的明确答案,该内容涉及内容拥抱和抗压缩性之间的区别。

有人可以解释他们的用法和区别吗?


49
人生最大的神秘之一就是为什么他们不简单地称其为“抗扩展性”。这两个特性无非是“抗扩展性”和“抗压缩性”。“拥抱”术语是疯狂的。
Fattie

3
如果您有太多的空间,则content-hugging:应对空白。这只会迫使视图绕过您。但是,如果您没有太多空间,而是只拥有很小的空间,那么content-compressions-resistance您将无法显示所有内容而与您的视图抗争,例如,标签将被截断。
亲爱的

Answers:


1319

概念的简要概述:

  • 拥抱=>内容不希望增长
  • 抗压强度=>含量不希望收缩

例:

假设您有一个这样的按钮:

[       Click Me      ]

并且您已将边缘固定到优先级为500的更大的超级视图。

然后,如果“拥抱优先级”> 500,它将如下所示:

[Click Me]

如果拥抱优先级<500,则它将如下所示:

[       Click Me      ]

如果现在缩小视图,那么如果“压缩抗性”优先级> 500,它将如下所示

[Click Me]

否则,如果“压缩抗性”优先级<500,则可能是这样的:

[Cli..]

如果这样不起作用,那么您可能还会遇到其他限制,使您的工作陷入混乱!

例如,您可以将其固定到具有优先级1000的超级视图。或者您可以具有宽度优先级。如果是这样,这可能会有所帮助:

编辑器>大小以适合内容


37
如果拥抱优先级== 500怎么办?
bradley.ayers 2013年

1
假设(但这通常不是一个好主意),它会像典型的舍入行为一样被视为> 500。还没有测试。
Joshua Nozzi 2013年

最有可能在运行时收到“无法同时满足约束条件”的警告
Max Desiatov

8
@ bradley.ayers对于MaxDesyatov的评论,只有在约束与“必需”优先级(1000)冲突时才会发生。如果两个优先级较低的约束发生冲突,则解决方案将不明确,因此“自动布局”引擎将只选择一个有效的解决方案,这就是您将看到的(无警告)。显然这不好,因为现在要由自动布局引擎的内部实现来选择布局的外观,并且从理论上讲,这可以从一个iOS版本更改为另一个iOS版本!
smileyborg 2014年

内容包含优先级默认值为250,而内容抗压缩性默认值为750。那么为什么要使用500?
ZYiOS 2015年

292

看一下有关Autolayout的视频教程,他们会仔细解释

在此处输入图片说明


1
@fatuhoku您可以再次检查吗,该视频是免费的
onmyway133 2014年

31
拥抱与抵抗的讨论始于视频中的13:15点。
卡尔·史密斯

1
@ onmyway133这是完美的视频,但不幸的是,没有任何示例Ray会如何使用它。
Matrosov Alexander 2014年

@MatrosovAlexander我觉得一个很现实的例子是动态的单元格高度带自动布局fantageek.com/1468/...
onmyway133

1
他在18:05演示了如何使用抗压强度
Brent Faust

187

在此处输入图片说明

资料来源:@mokagio

内在内容大小 -很明显,但具有可变内容的视图会知道其内容的大小,并通过此属性描述其内容的大小。具有内在内容大小的视图的一些明显示例是UIImageViews,UILabels,UIButtons。

内容拥抱优先级 -此优先级越高,视图抵抗其自身内容大小增长的能力就越大。

内容压缩抗性优先 -此优先级越高,视图抵抗收缩的能力就小于其固有内容大小。

在此处查看更多说明:自动布局魔术:内容大小优先


插图很好,但至少可以说是误导。高层应该说:“我不会(让我)成长”。子视图自行定义它不想通过其内容拥抱行为而增长。没有外力(如图示的手)阻止其生长。那是很大的不同。
曼努埃尔

6
我之所以投票是因为我喜欢这个插图。
James Bucanek

3
这就是为什么我喜欢Stack Overflow…Snowcrash的描述以及mokagio的插图=任何地方这些属性的最佳解释(包括Apple自己的文档)。
Kal

40

假设您有一个带有文本“ Click Me”的按钮。该按钮应该是多少宽度?

首先,您绝对不希望按钮小于文本。否则,文本将被剪切。这是水平压缩阻力优先级。

其次,您不希望按钮大于所需的大小。看起来像这样的按钮[Click Me]太大了。您希望按钮在没有太多填充的情况下“拥抱”其内容。这是优先考虑的水平内容。对于按钮,它不如水平抗压优先级强。


19

如果为view.intrinsicContentSize.width != NSViewNoIntrinsicMetric,则自动布局会创建类型的特殊约束NSContentSizeLayoutConstraint。此约束的行为类似于两个常规约束:

  • 约束条件 view.width <= view.intrinsicContentSize.width水平拥抱优先权,以及
  • 需要view.width >= view.intrinsicContentSize.width具有水平抗压性优先级的约束。

在Swift中,借助iOS 9的新布局锚点,您可以设置类似的约束,如下所示:

let horizontalHugging = view.widthAnchor.constraint(
    lessThanOrEqualToConstant: view.intrinsicContentSize.width)
horizontalHugging.priority = view.contentHuggingPriority(for: .horizontal)

let horizontalCompression = view.widthAnchor.constraint(
    greaterThanOrEqualToConstant: view.intrinsicContentSize.width)
horizontalCompression.priority = view.contentCompressionResistancePriority(for: .horizontal)

类似地,如果为view.intrinsicContentSize.height != NSViewNoIntrinsicMetric,则自动布局会创建一个NSContentSizeLayoutConstraint对视图高度起两个约束作用的。在代码中,它们看起来像这样:

let verticalHugging = view.heightAnchor.constraint(
    lessThanOrEqualToConstant: view.intrinsicContentSize.height)
verticalHugging.priority = view.contentHuggingPriority(for: .vertical)

let verticalCompression = view.heightAnchor.constraint(
    greaterThanOrEqualToConstant: view.intrinsicContentSize.height)
verticalCompression.priority = view.contentCompressionResistancePriority(for: .vertical)

您可以在布局运行后NSContentSizeLayoutConstraint通过打印来查看这些特殊实例(如果存在)view.constraints。例:

label.constraints.forEach { print($0) }

// Output:
<NSContentSizeLayoutConstraint:0x7fd82982af90 H:[UILabel:0x7fd82980e5e0'Hello'(39)] Hug:250 CompressionResistance:750>
<NSContentSizeLayoutConstraint:0x7fd82982b4f0 V:[UILabel:0x7fd82980e5e0'Hello'(21)] Hug:250 CompressionResistance:750>

1
应该不是:let verticalCompression = view.heightAnchor.constraint(GreaterThanOrEqualToConstant:view.intrinsicContentSize.height)
mc_plectrum

1
是的,我犯了一个复制/粘贴错误。我已经改正了。谢谢你让我知道。
rob mayoff

15

内容拥抱和内容压缩优先级适用于可以根据传入内容本质上计算其大小的元素。

来自Apple文档

在此处输入图片说明


图片的plus1(Y)
Noor Ali Butt 2016年

我糊涂了。对于未启用滚动的textView。这是否意味着每个用户键入的固有大小都会改变?
亲爱的

@Honey我认为在设置了正确的约束并且禁用了滚动的情况下,文本视图应该能够分辨出固有高度。
dev gr

那没有回答我的问题。您的意思是,如果我输入的内容很多,超过当前textView的大小...。textView是否会自动展开并更改固有大小?
亲爱的

自己尝试。给textview一个固定的宽度,并禁用滚动并检查所需的行为。请参阅stackoverflow.com/a/21287306/1526629了解更多答案。
dev gr

11

Content hugging priority是像橡皮筋,其周围放置的图。优先级值越高,橡皮筋越结实,它越想拥抱其内容物大小。可以将优先级值想象成橡皮筋的“强度”

而且Content Compression Resistance是,多少钱景“光刻胶”越来越小了 具有较高优先级的电阻值的视图是一个将抗压缩。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.