语言: swift, 版本:swift5,XCode:10.2
写作时间:2019-06-19
Introduction to SnapKit: Make Auto Layout Easy for iOS App Development
相对布局,Swift用SnapKit,跟Objc用Masonry是一个团队维护的,所以语法糖都一毛一样。github Star > 1.5w, 信得过!
Demo gif:
注意:设置相对布局之前,前置条件为把addSubview加入父视图
跟父界面的布局一毛一样,也就是逆时针方向上左下右,可以设置距离边界偏移量offset(上和左是用正数,下和右是用负数表示缩进), 设置优先级priority,默认是1000; 常用情况的subview的是3个方向跟父界面相对,缺少一个方向,用高度或者宽度定位:
viewTop = UIView()
viewContainer.addSubview(viewTop)
viewTop.backgroundColor = innerViewBGColor
viewTop.snp.makeConstraints { (make) in
make.top.equalTo(viewContainer).offset(40).priority(750)
make.left.equalTo(viewContainer)
make.bottom.equalTo(viewContainer)
make.right.equalTo(viewContainer)
//make.height.equalTo(100)
}
如果跟父视图都一致,有内边距可以用UIEdgeInsets:
lblTitle.snp.makeConstraints { (make) in
make.edges.equalTo(viewTop).inset(UIEdgeInsets(top: 0.0, left: 16.0, bottom: 0.0, right: 0.0))
}
保存约束self.centerYConstraint,实际上上面Y方向已经居中
func setupContainerView() {
viewContainer = UIView()
self.addSubview(viewContainer)
viewContainer.snp.makeConstraints { (make) in
self.centerYConstraint = make.centerY.equalTo(self).constraint
}
}
更新Y方向向下偏移10px:
centerYConstraint.update(offset: 10)
self.setNeedsLayout()
UIView.animate(withDuration: 0.4) {
self.layoutIfNeeded()
}
上面为啥centerYConstraint跟make的用法一样? 这是链式设计模式,也就是left, top, centerY, 等方法返回都是self自己。比如left, top都是跟父视图一样,也可以这么写:
viewTop.snp.makeConstraints { (make) in
make.left.top.equalTo(viewContainer)
// the same as below
// make.left.equalTo(viewContainer)
// make.top.equalTo(viewContainer)
}
看源码是如何使用链式设计模式的:
public var left: ConstraintMakerExtendable {
self.description.attributes += .left
return self
}
public var top: ConstraintMakerExtendable {
self.description.attributes += .top
return self
}
public var bottom: ConstraintMakerExtendable {
self.description.attributes += .bottom
return self
}
public var right: ConstraintMakerExtendable {
self.description.attributes += .right
return self
}
清空原有约束,重新定义约束用remakeConstraints:
txtEmail.snp.remakeConstraints { (make) in
make.top.equalTo(viewTop.snp.bottom).offset(16)
make.left.equalTo(viewContainer).offset(8)
make.right.equalTo(viewContainer).offset(-8)
make.height.equalTo(textfieldHeight)
}
如果原有约束存在,需要更新约束 updateConstraints:
activityIndicator.snp.updateConstraints { (make) in
make.centerY.equalTo(viewContainer).offset(-containerViewHeight/2 - 20)
}
view自己调用的方法,方法中的参数make又是自己,为啥不会循环引用
btnConnect.snp.makeConstraints { (make) in
make.top.equalTo(viewBottom)
make.right.equalTo(viewBottom)
make.bottom.equalTo(viewBottom)
make.width.equalTo(connectButtonWidth)
}
看源码可以知道端倪,方法中的block没有被self引用,也就不会存在循环引用。
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.makeConstraints(item: self.view, closure: closure)
}
SnapKit 用第一节的方法可以解决80%的常见布局功能,有动画需求参照下面的3个小节也可以解决。完整教程请参照:Introduction to SnapKit: Make Auto Layout Easy for iOS App Development
https://github.com/zgpeace/SnapkitDemo
https://www.appcoda.com/snapkit/
https://github.com/SnapKit/SnapKit
https://github.com/SnapKit/Masonry