The content hugging 向内拉视图,使其紧贴内容. The compression resistance 将视图向外推,以使其不会剪切内容。 priority 学习需要了解 intrinsicContentSize 属性
Content-Hugging Priotity: 拥抱优先级(抗拉伸优先级)默认 250,等级越高自己就保持不变,别的控件拉伸。
Compression-Resistance Priotity :抗压缩优先级默认 750,等级越高自己保持不变,别的控件压缩。
每个 constraint 都有它的优先级,默认 content hugging 250 compression resistance 750,因此 view 更容易拉伸,不易收缩。这也是大部分期望的行为。比如 button 我们更希望安全的拉伸并超过固有内容尺寸,而不是希望收缩导致内容被截取。
CHCR 和 Intrinsic Content Size 指导
- 当需要拉伸 view 填充空间,如果 views 都是完全相同的 content-hugging priority,Auto Layout 也不知道哪个 view 拉伸。
一个常见的例子,一对 label 和 textfield 通常我们都希望 textfield 拉伸来占满剩下的空间 label 展示其固有尺寸,为了有这个效果,我们就需要让
textfield 的 content hugging 等级小于label。
事实上,如果使用的是 xib 或者 storyboard 会自动把 label 的 content hugging priority 设置为 251,如果你是手写代码,就需要手动更改优先级。
-
baseline constraint 是基于 intrinsicContentSize 的高展示,如果 view 的垂直方向发生 拉伸或者收缩,baseline constraint 就不再是一个正确的对齐属性了。
-
一些 views 比如 switch 默认是以 intrinsicContentSize 展示,我们可以为它指定优先级,以防它被压缩或者拉伸。
-
避免给 view 分配一个 require(1000)级别的 CHCR property,一个错误的位置总好过一个突然出现的约束冲突。如果我们想让 view 保持intrinsicContentSize 显示,我们可以给他分配一个 999 的优先级(最高 1000),这个级别能尽可能保证 view 不被压缩或者拉伸的同时,也可以给它一个紧急压缩的可能,以防万一出现一个更大或者更小的情况。
实际使用
Label 和 Textfield: 我们希望 textfield 拉伸,label 展示intrinsicContentSize。
1.pngnamePriorityLabel.setContentHuggingPriority(UILayoutPriority (251), for: .horizontal)
两个 label:
- 我们希望一个显示 intrinsicContentSize ,另一个换行。
2.pnglabelPriorityOne.setContentCompressionResistancePriority(UILayoutPriority (999), for: .horizontal)
- 一个正常展示,另一个拉伸占满剩下的空间
3.png实现这个功能 ,并没有指定某个 label 的约束优先级,但是我发现 self.labelThree 的优先级高于 self.labelFour.
NSLayoutConstraint.activate([
self.labelThree.topAnchor.constraint(equalTo: self.labelPriorityTwo.bottomAnchor,constant: 20),
self.labelThree.leftAnchor.constraint(equalTo: layoutMarginsConstraint.leftAnchor),
self.labelFour.topAnchor.constraint(equalTo:self.labelPriorityTwo.bottomAnchor,constant: 20),
self.labelFour.leftAnchor.constraint(equalTo: self.labelThree.rightAnchor),
self.labelFour.rightAnchor.constraint(equalTo: layoutMarginsConstraint.rightAnchor),
])
4.png现在更改约束顺序,但是我发现 self.labelFour 的优先级高于 self.labelThree
NSLayoutConstraint.activate([
self.labelFour.topAnchor.constraint(equalTo:self.labelPriorityTwo.bottomAnchor,constant: 20),
self.labelFour.leftAnchor.constraint(equalTo: self.labelThree.rightAnchor),
self.labelFour.rightAnchor.constraint(equalTo: layoutMarginsConstraint.rightAnchor),
self.labelThree.topAnchor.constraint(equalTo: self.labelPriorityTwo.bottomAnchor,constant: 20),
self.labelThree.leftAnchor.constraint(equalTo: layoutMarginsConstraint.leftAnchor),
])
Note:
这个现象通过 snapkit 进行布局也是一样的,那么我们可以大胆地假设: 两个相同的控件,后约束的控件 优先级高于 先约束的。
cell 有一个 ImageView 背景: 我们一般写都是希望 cell 高度自适应, 所以cell 的 bottom 会和最后一个 view bottom。但是如果背景是image ,cell 就会根据 image size 显示,我们要做的就是把 image的 priority 调低。
// 设置一下 竖直方向的 优先级
tempImageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
网友评论