SnapKit简介
-
SnapKit
是一个优秀的第三方自适应布局库,它可以让iOS、OS X应用更简单地实现自动布局(Auto Layout)。它的作者仍然是写Objective-C的第三方库Masonry的大牛 - @Robert Payne -
下载链接 SnapKit
SnapKit配置
-
在项目工程里的Podfile文件里面添加
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! target '这里是你的工程名称' do pod 'SnapKit', '~> 3.0' end
-
运行CocoaPods命令
pod install
-
引入头文件
import SnapKit
import UIKit import SnapKit
SnapKit使用
-
示例:
testView.snp.makeConstraints { (make) in make.left.equalToSuperview().offset(50) make.right.equalToSuperview().offset(-50) make.top.equalToSuperview().offset(50) make.bottom.equalToSuperview().offset(-50) }
-
基本格式:(
make .
指定其的一个属性.
约束关系)make.attr.constrains
-
make
:可认为是要布局的view的代理constrains
:约束可能是多级的组合,比如make.left.equalToSuperview().offset(50)
的两级组合,显示找到父view
的左边位置,再向右(X轴)移动50点
给控件添加、更新约束、引用约束、停用、启用
-
添加新的约束
testView.snp.makeConstraints { (make) in }
-
删除控件以前所有约束,添加新约束
testView.snp.remakeConstraints { (make) in }
-
更新约束,写哪条更新哪条,其他约束不变
testView.snp.updateConstraints { (make) in }
-
引用约束,声明一个局部变量或者类属性来引用要修改的约束
var topConstraint: Constraint? = nil override func viewDidLoad() { super.viewDidLoad() let testView = UIView() testView.backgroundColor = UIColor.red self.view.addSubview(testView) testView.snp.makeConstraints { (make) in self.topConstraint = make.left.equalToSuperview().offset(100).constraint make.right.equalToSuperview().offset(-100) make.top.equalToSuperview().offset(100) make.bottom.equalToSuperview().offset(-100) } }
-
停用
self.topConstraint?.deactivate()
-
启用
self.topConstraint?.activate()
设置约束关系
约束关系 | 说明 |
---|---|
equalTo() |
设置属性等于某个数值 |
greaterThanOrEqualTo() |
设置属性大于或等于某个数值 |
lessThanOrEqualTo() |
设置属性小于或等于某个数值 |
multipliedBy() |
设置属性乘以因子后的值 |
dividedBy() |
设置属性除以因子后的值 |
- Snapkit 的 greaterThanOrEqualTo 属性
如果想让视图View2的左边>=父视图View1的左边, 这时我们就可以用到greaterThanOrEqualTo
///黑色视图作为父视图 let view1 = UIView() view1.frame = CGRect(x: 0.0, y: 0.0, width: 300, height: 300) view1.center = view.center view1.backgroundColor = .black view.addSubview(view1) ///测试视图 let view2 = UIView() view2.backgroundColor = .magenta view1.addSubview(view2) view2.snp.makeConstraints { (make) in make.top.equalTo(view1.snp.bottom).offset(10) make.width.height.equalTo(100) make.left.greaterThanOrEqualTo(view1) }
效果图
- lessThanOrEqualTo的用于上、下、左、右
如果我们想要视图view2的左边 <= view1.left + 10, 那么就可以直接用到lessThanOrEqualTo布局了,看下面这个例子
let view1 = UIView() view1.frame = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0) view1.center = view.center view1.backgroundColor = .black view.addSubview(view1) let view2 = UIView() view2.backgroundColor = .magenta view1.addSubview(view2) view2.snp.makeConstraints { (make) in make.left.lessThanOrEqualTo(20.0) //<= 父视图的左边+20 make.right.equalTo(-40.0) // = 父视图的右边-40 make.height.equalTo(100.0) make.center.equalToSuperview() }
-
SnapKit的greaterThanOrEqualTo和lessThanOrEqualTo联合使用
当我们想要让某个视图的width或height大于等于某个特定的值,小于等于某个特定的值的时候,一般而言,Snapkit会以greaterThanOrEqualTo为准,这里举一个width的例子,为了方便,这里指贴出了viewDidLoad中的代码(其他没必要)
let view1 = UIView() view1.frame = CGRect(x: 0.0, y: 0.0, width: 300.0, height: 300.0) view1.center = view.center view1.backgroundColor = .black view.addSubview(view1) let view2 = UIView() view2.backgroundColor = .magenta view1.addSubview(view2) view2.snp.makeConstraints { (make) in make.width.lessThanOrEqualTo(300) make.width.greaterThanOrEqualTo(200) make.height.equalTo(100) make.center.equalToSuperview() }
接着,我们来看一下效果图
很明显,最后的宽度是以make.width.greaterThanOrEqualTo(200)为标准的,也可以这样的,在同时使用两者的情况下,greaterThanOrEqualTo的优先级略比lessThanOrEqualTo的优先级高。值得一提的是, 在上面的例子中,如果我们只设置make.width.lessThanOrEqualTo(300),那么view2是不会显示出来的,因为view2不知道你要表达的是要显示多少,小于等于300,到底是100还是200呢?(这里指针对width和height)所以它不能确定这个约束的值,但是,如果我们单独设置make.width.greaterThanOrEqualTo(200),那么就和上面的效果一样,因为它会以200为标准布局约束!
设置控件布局属性
布局属性 | 说明 |
---|---|
尺寸 | width 、height 、size |
边距 | left 、top 、right 、bottom 、leading 、trailing |
中心点 | center 、centerX 、centerY |
边界 | edges |
//iOS8之后Masonry新出了几个属性: //距离边框的距离,等同于选中Storyboard的Constrain to margins后加约束public var leftMargin: SnapKit.ConstraintMakerExtendable { get } public var rightMargin: SnapKit.ConstraintMakerExtendable { get } public var topMargin: SnapKit.ConstraintMakerExtendable { get } public var bottomMargin: SnapKit.ConstraintMakerExtendable { get } public var leadingMargin: SnapKit.ConstraintMakerExtendable { get } public var trailingMargin: SnapKit.ConstraintMakerExtendable { get } public var centerXWithinMargins: SnapKit.ConstraintMakerExtendable { get } public var centerYWithinMargins: SnapKit.ConstraintMakerExtendable { get }
其中leading
与left
,trailing
与right
在正常情况下是等价的,但是当一些布局是从右至左时(比如阿拉伯文) 则会对调
设置约束偏移
方法 | 参数 | 说明 |
---|---|---|
offset(CGFloat offset) |
CGFloat |
控件属性相对于参照物偏移多少 |
insets(MASEdgeInsets insets) |
MASEdgeInsets |
控件四边相对于参照物偏移多少 |
-
offset
示例testView.snp.makeConstraints { (make) in make.left.equalToSuperview().offset(20) make.right.equalToSuperview().offset(-20) make.top.equalToSuperview().offset(20) make.bottom.equalToSuperview().offset(-20) }
-
insets
示例刚开始使用 SnapKit 时,我都是直接使用
offset
来控制边距的:view.snp.makeConstraints { $0.top.left.equalToSuperview().offset(10) $0.right.bottom.equalToSuperview().offset(-10) }
offset
使用的是绝对值,例如说superview
的bottom
是 300 时,那view
的bottom
就会是300 + (-10)
。为了简化在这种情况下的语法,SnapKit 封装了一个高级抽象
inset
,帮我们自动转换:switch layoutAttribute { case .left : return value.left case .top : return value.top case .right : return -value.right case .bottom : return -value.bottom ... }
使用
inset
,之前的代码就可以简化成这样:view.snp.makeConstraints { $0.top.left.bottom.right.equalToSuperview().inset(10) // 或者直接使用 edges $0.edges.equalToSuperview().inset(10) }
总结一句就是,在描述 view 与 superview 关系时,应该使用
inset
,而描述 view 与同一层级的其它 view 时,应该使用offset
。
设置约束优先级
-
SnapKit为我们提供了三个默认的方法,
required
、high
、medium
、low
,优先级最大数值是1000public static var required: ConstraintPriority { return 1000.0 } public static var high: ConstraintPriority { return 750.0 } public static var medium: ConstraintPriority { #if os(OSX) return 501.0 #else return 500.0 #endif } public static var low: ConstraintPriority { return 250.0 }
-
自己设置优先级的值,可以通过
priority()
方法来设置testView.snp.makeConstraints { (make) in make.center.equalToSuperview() make.width.equ alTo(100).priority(ConstraintPriority.low) make.width.equalTo(100).priority(ConstraintPriority.high) make.height.equalTo(100).priority(200) make.height.equalTo(50).priority(800) }
Snapkit布局的灵活性
- Snapkit布局灵活性很强, 我们看下面的例子, 他们的效果是一样的
make.left.equalToSuperview().offset(10) make.left.equalTo(10) make.left.equalTo(view1.snp.left).offset(10)
-
设置视图的大小(width,height),他们效果是一样的
make.width.height.equalTo(100) 或 make.width.equalTo(100) make.height.equalTo(100) 或 make.size.equalTo(CGSize(width: 100, height: 100))
SnapKit 注意
- 使用SnapKit添加约束之前,需要在
addSubview
之后才能使用,否则会导致崩溃 - 在添加约束时常会出现一些错误,约束出现问题的原因一般就是两种:约束冲突和缺少约束。对于这两种问题,可以通过调试和log排查