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排查