当约束条件发生冲突时,系统会使用用优先级高的约束。
还可以通过设置约束为 deactive
状态来使约束不生效。
利用好约束的优先级,可以使布局代码简洁、逻辑清晰。
系统原生的 AutoLayout 代码写起来太冗长了,使用 SnapKit 来演示如何运用约束优先级,方便理解逻辑。
场景 1 动态调整间距
当有图片的时候布局如下:
如果没有图片,文字布局如下:
imageView 的布局代码:
imageView.snp.makeConstraints { (make) in
make.size.equalTo(CGSize(width: 80, height: 80))
make.top.equalTo(100)
make.right.equalTo(-30)
}
titleLabel 的布局代码:
var c: SnapKit.ConstraintMakerFinalizable!
titleLabel.snp.makeConstraints { (make) in
make.top.equalTo(100)
make.left.equalTo(30)
c = make.right.equalTo(imageView.snp.left).offset(-10)
make.right.equalTo(-30).priorityMedium()
}
对于 UILabel ,还需要降低其抗压缩优先级:
titleLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
对 titleLable 添加两条 right 约束,并降低其中一条的优先级为 medium:
make.right.equalTo(imageView.snp.left).offset(-10)
make.right.equalTo(-30).priorityMedium()
当需要显示图片时:
imageView.isHidden = false
c.constraint.activate()
没有图片时,隐藏 imageView:
imageView.isHidden = true
c.constraint.deactivate()
场景 2 动态调整宽度
布局需要满足以下需求:
- 在手机上保持左右间距为:15
- 在平板上使用固定宽度:320
手机上的布局效果:
平板上的布局效果:
可以把平板抽象为与设备无关的逻辑,目前手机上最大的尺寸是 Pro Max
,它的屏幕宽度是 414。
宽度大于 414 就认为是运行于平板设备上。
布局代码如下:
var c: SnapKit.ConstraintMakerFinalizable!
containerView.snp.makeConstraints { (make) in
make.left.equalTo(15).priorityLow()
make.right.equalTo(-15).priorityLow()
c = make.width.equalTo(320).priorityMedium()
make.centerX.equalTo(view)
make.height.equalTo(200)
if #available(iOS 11.0, *) {
make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom).offset(-30)
} else {
make.bottom.equalTo(-30)
}
}
通过约束 left
和 right
就能确定宽度了,再添加一条设置 width
的约束来控制最小宽度。
添加的 centerX
约束是保证 width
约束生效的时候能确定其 X 坐标位置。
不同屏幕尺寸下的显示逻辑:
if view.frame.width <= 414 {
c.constraint.deactivate()
} else {
c.constraint.activate()
}
场景 3 保持最小间距同时限制最大宽度
布局要求满足以下需求:
- 在 5s 上左右间距为 20
- 在 6 plus 以及更宽的屏幕上保持最大宽度为 335
- 水平居中显示
利用约束优先级来实现非常简单,实现代码如下:
containerView.snp.makeConstraints { (make) in
make.left.greaterThanOrEqualTo(20).priorityHigh()
make.right.lessThanOrEqualTo(-20).priorityHigh()
make.width.equalTo(335).priorityMedium()
make.centerX.equalTo(view)
}
场景 4 在 UIScrollView 里居中
布局要求满足以下需求:
- 上下保留最小间距 20
- 左右保留最小间距 20
- 如果空间足够则居中显示
- 空间不够需要能滑动查看
- 宽和高为 335 x 520
UIScrollView 的子控件使用自动布局时,contentSize
的大小由子控件的水平约束和垂直约束决定。
实现代码:
containerView.snp.makeConstraints { (make) in
// 水平方向的约束
make.left.greaterThanOrEqualTo(20).priorityHigh()
make.right.lessThanOrEqualTo(-20).priorityHigh()
make.width.equalTo(335).priorityMedium()
make.centerX.equalTo(scrollView)
// 垂直方向的约束
make.top.greaterThanOrEqualTo(20).priorityHigh()
make.bottom.lessThanOrEqualTo(-20).priorityHigh()
make.height.equalTo(520).priorityMedium()
make.centerY.equalTo(scrollView).priorityMedium()
}
(完)