swift约束框架SnapKit使用

 
为了适应各种屏幕尺寸,iOS 6后引入了自动布局(Auto Layout)的概念,通过使用各种 Constraint(约束)来实现页面自适应弹性布局。(想了解更多可查看我原来写的这篇文章:Swift - 使用Auto Layout和Size Classes实现页面自适应弹性布局
在 StoryBoard 中使用约束实现自动布局很方便,但如果用纯代码来设置约束就很麻烦了。这里向大家推荐一个好用的第三方布局库:SnapKit(其前身是 Masonry,一个OC版的布局库)

1,SnapKit介绍 
SnapKit是一个优秀的第三方自适应布局库,它可以让iOS、OS X应用更简单地实现自动布局(Auto Layout)。
GtiHub地址:https://github.com/SnapKit/SnapKit
 
2,SnapKit配置
(1)将下载下来的SnapKit项目的 SnapKit.xcodeproj 拖进自己的项目目录当中
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)

(2)在 工程 -> General -> Embedded Binaries 中点击加号,添加SnapKit库到项目中来 
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)

3,先看一个简单的使用样例
在页面正中央放置一个100*100的正方形view
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
    lazy var box = UIView()
 
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.width.equalTo(100)
            make.height.equalTo(100)
            make.center.equalTo(self.view)
        }
    }
}
由于长宽都一样,我们还可以串连视图属性,增加可读性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
    lazy var box = UIView()
 
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(100)
            make.center.equalTo(self.view)
        }
    }
}

4,SnapKit的使用方法
通过 snp_makeConstraints 方法给view添加约束,约束有几种,分别是边距,宽,高,左上右下距离,基准线。同时,添加过约束后可以有修正,修正有位移修正(inset、offset)和倍率修正(multipliedBy)
语法一般是: make.equalTo 或 make.greaterThanOrEqualTo 或 make.lessThanOrEqualTo + 倍数和位移修正。

.equalTo:等于 
.lessThanOrEqualTo:小于等于
.greaterThanOrEqualTo:大于等于
注意: 使用 snp_makeConstraints 方法的元素必须事先添加到父元素的中,例如:self.view.addSubview(view)

5,约束条件参数支持如下三种类型:
(1)视图属性(ViewAttribute)
视图属性(ViewAttribute) 布局属性(NSLayoutAttribute)
view.snp_left NSLayoutAttribute.Left
view.snp_right NSLayoutAttribute.Right
view.snp_top NSLayoutAttribute.Top
view.snp_bottom NSLayoutAttribute.Bottom
view.snp_leading NSLayoutAttribute.Leading
view.snp_trailing NSLayoutAttribute.Trailing
view.snp_width NSLayoutAttribute.Width
view.snp_height NSLayoutAttribute.Height
view.snp_centerX NSLayoutAttribute.CenterX
view.snp_centerY NSLayoutAttribute.CenterY
view.snp_baseline NSLayoutAttribute.Baseline
1
2
//使当前视图对象的中心x坐标小于等于视图view2的左边的x坐标
make.centerX.lessThanOrEqualTo(view2.snp_left)

(2)视图关系(UIView/NSView) 
比如想让view.left 大于等于 label.left:
1
make.left.greaterThanOrEqualTo(label)
这个其实等价于:
1
make.left.greaterThanOrEqualTo(label.snp_left)

(3)严格检测(Strick Checks)
比如将宽度和高度属性设置为常量值:
1
2
3
make.height.equalTo(20)
make.width.equalTo(20)
make.top.equalTo(42)

6,给视图的各种属性设置约束
(1)width、height属性
自动布局允许宽度、高度设置为常量值。
1
2
3
4
make.height.equalTo(20)
make.width.equalTo(self.buttonSize.width)
//当前视图与label的顶部齐平
make.top.equalTo(label.snp_top)

(2) left、right、top、centerX、centerY等其他属性
这些属性直接设置常量值,表示他们相对于父容器的相对约束条件。比如我们将绿色方块放置橙色方块内部的右下角位置。
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    //外部方块
    lazy var boxOutter = UIView()
    //内部方块
    lazy var boxInner = UIView()
 
    override func viewDidLoad() {
        super.viewDidLoad()
         
        boxOutter.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(boxOutter)
        boxInner.backgroundColor = UIColor.greenColor()
        boxOutter.addSubview(boxInner)
         
        boxOutter.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(200)
            make.center.equalTo(self.view)
        }
         
        boxInner.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(100)
            make.right.equalTo(0)
            make.bottom.equalTo(0)
        }
    }
}
当然也可以使用与其他视图的关系来添加约束。比如:下面绿色方块视图大小同上面橙色方块相同,下面视图与上面视图左侧平齐,下面视图顶部与上面视图底部平齐。
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    //方块1
    lazy var box1 = UIView()
    //方块2
    lazy var box2 = UIView()
 
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box1.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box1)
        box2.backgroundColor = UIColor.greenColor()
        self.view.addSubview(box2)
         
        box1.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(20)
            make.right.equalTo(-20)
            make.height.equalTo(40)
            make.top.equalTo(20)
        }
         
        box2.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(box1)
            make.left.equalTo(box1) //等同于 make.left.equalTo(box1.snp_left)
            make.top.equalTo(box1.snp_bottom)
        }
    }
}

(3)edges(边缘)
1
2
//让当前视图 的 上下左右(top,left,bottom,right) 等于 view2
make.edges.equalTo(view2)

(4)size(尺寸)
1
2
//当前视图宽高 >= titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

(5)center(中心)
1
2
//当前视图与 button1中心相同 (centerX 和 centerY)
make.center.equalTo(button1)

7,位移修正与倍率修正
(1)内位移修正:inset
比如下图中绿色视图view,它距离父视图上、左、下、右边距分别是10、15、20、25
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    //外部方块
    lazy var boxOutter = UIView()
    //内部方块
    lazy var boxInner = UIView()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        boxOutter.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(boxOutter)
        boxInner.backgroundColor = UIColor.greenColor()
        boxOutter.addSubview(boxInner)
         
        boxOutter.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(200)
            make.center.equalTo(self.view)
        }
         
        boxInner.snp_makeConstraints { (make) -> Void in
            make.edges.equalTo(boxOutter).inset(UIEdgeInsetsMake(10, 15, 20, 25))
        }
    }
}
上面边距的偏移设置实际上相当于如下形式:
1
2
3
4
make.top.equalTo(boxOutter).offset(10)
make.left.equalTo(boxOutter).offset(15)
make.bottom.equalTo(boxOutter).offset(-20)
make.right.equalTo(boxOutter).offset(-25)

(2)外位移修正:offset 
下面让绿色视图比橙色视图宽度加50,高度减50。
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    //外部方块
    lazy var boxOutter = UIView()
    //内部方块
    lazy var boxInner = UIView()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        boxOutter.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(boxOutter)
        boxInner.backgroundColor = UIColor.greenColor()
        boxOutter.addSubview(boxInner)
         
        boxOutter.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(200)
            make.center.equalTo(self.view)
        }
         
        boxInner.snp_makeConstraints { (make) -> Void in
            make.center.equalTo(boxOutter)
            // make width = superview.width + 100, height = superview.height - 50
            make.size.equalTo(boxOutter).offset(CGSizeMake(50, -50))
        }
    }
}

(3)倍率修正:multipliedBy 
下面将绿色视图的尺寸设置成橙色视图一半大小。
原文:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    //外部方块
    lazy var boxOutter = UIView()
    //内部方块
    lazy var boxInner = UIView()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        boxOutter.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(boxOutter)
        boxInner.backgroundColor = UIColor.greenColor()
        boxOutter.addSubview(boxInner)
         
        boxOutter.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(200)
            make.center.equalTo(self.view)
        }
         
        boxInner.snp_makeConstraints { (make) -> Void in
            make.center.equalTo(boxOutter)
            // make width = superview.width / 2, height = superview.height / 2
            make.size.equalTo(boxOutter).multipliedBy(0.5)
        }
    }
}
 


二、Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)

在之前的文章中我介绍了如何使用SnapKit的 snp_makeConstraints 方法进行各种约束的设置。但有时我们的页面并不是一直固定不变的,这就需要修改已经存在的约束。本文介绍如何更新、移除、代替现有的约束。
 
1,删除约束
要实现对现有的约束进行更新或者移除,我们需要先将约束的结果赋值给一个局部变量或一个类属性,然后对这个约束的引用进行操作。
比如下面样例:开始时我们给橙色方块添加了个距屏幕上方40像素的约束,点击按钮后使用 uninstall() 方法把这个约束给移除。
      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    //保存约束的引用
    var topConstraint:Constraint?
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(150)
            make.centerX.equalTo(self.view)
            self.topConstraint = make.top.equalTo(self.view).offset(40).constraint
        }
    }
     
    //按钮点击
    @IBAction func btnTouch(sender: AnyObject) {
        //移除约束
        self.topConstraint?.uninstall()
    }
}

2,通过约束的引用来更新约束
还是以上面距屏幕上方40像素的约束为例,点击按钮后,通过调用约束引用的 updateOffset() 方法把距离修改成60像素。
      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    //保存约束的引用
    var topConstraint:Constraint?
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(150)
            make.centerX.equalTo(self.view)
            self.topConstraint = make.top.equalTo(self.view).offset(40).constraint
        }
    }
     
    //按钮点击
    @IBAction func btnTouch(sender: AnyObject) {
        //更新修改约束
        self.topConstraint?.updateOffset(60)
    }
}

3,使用snp_updateConstraints更新约束
我们还可以用 snp_updateConstraints 方法来代替 snp_makeConstraints 进行约束的更新,这个更新操作通常放在 UIViewController 的 updateViewConstraints() 方法中,或者 UIView 的 updateConstraints() 方法中执行,这样视图约束需要更新的时候会自动调用。
比如下面样例,我们使用 snp_updateConstraints() 方法设置橙色视图的宽度约束为与屏幕等宽,这样不管设备如何旋转,视图都回自动更新约束撑满屏幕。
      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.height.equalTo(150)
            make.centerX.equalTo(self.view)
        }
    }
   
    //视图约束更新
    override func updateViewConstraints() {
        self.box.snp_updateConstraints{ (make) -> Void in
            //视图宽度与屏幕等宽
            make.width.equalTo(self.view)
        }
   
        super.updateViewConstraints()
    }
}

4,使用snp_remakeConstraints重做约束
snp_remakeConstraints 与 snp_makeConstraints 用法类似,不同的是 snp_remakeConstraints 首先会先清除掉之前所有被SnapKit设置的约束。
下面样例:初始化时橙色视图约束是宽高150,水平居中。点击按钮后重做约束,宽高变100,且不再居中。
      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)      原文:Swift - 自动布局库SnapKit的使用详解2(约束的更新、移除、重做)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            make.width.height.equalTo(150)
            make.centerX.equalTo(self.view)
        }
    }
   
    //按钮点击
    @IBAction func btnTouch(sender: AnyObject) {
        //重做约束
        box.snp_remakeConstraints { (make) -> Void in
            make.width.height.equalTo(100)
        }
    }
}


三、Swift - 自动布局库SnapKit的使用详解3(约束优先级,约束做动画)

1,约束优先级
我们使用SnapKit的时候,还可以定义约束的优先级。这样当约束出现冲突的时候,优先级高的约束覆盖优先级低的约束。具体优先级可以放在约束链的结束处。
 
(1)可以设置如下几种优先级
priorityLow():设置低优先级,优先级为250
priorityMedium():设置中优先级,优先级为500(这个也就是默认的优先级)
priorityHigh():设置高优先级,优先级为750
priority():可以设置任意的优先级,接受的参数是0-1000的数字。比如:priority(600)

(2)使用优先级的样例
下面我们在屏幕中央放置一个100*100的橙色方块,给其定义了长宽尺寸小于等于屏幕的大小的默认优先级约束。同时,每次点击屏幕的时候,会更新放大它的尺寸。但由于这个约束的优先级是低,所有方块顶到屏幕边缘后就会不再放大。
  原文:Swift - 自动布局库SnapKit的使用详解3(约束优先级,约束做动画)  原文:Swift - 自动布局库SnapKit的使用详解3(约束优先级,约束做动画)  原文:Swift - 自动布局库SnapKit的使用详解3(约束优先级,约束做动画)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    var scacle = 1.0
    
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //单击监听
        let tapSingle=UITapGestureRecognizer(target:self,action:#selector(tapSingleDid))
        tapSingle.numberOfTapsRequired=1
        tapSingle.numberOfTouchesRequired=1
        self.view.addGestureRecognizer(tapSingle)
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            //视图居中
            make.center.equalTo(self.view)
            //初始宽、高为100(优先级低)
            make.width.height.equalTo(100 * self.scacle).priorityLow();
            //最大尺寸不能超过屏幕
            make.width.height.lessThanOrEqualTo(self.view.snp_width)
            make.width.height.lessThanOrEqualTo(self.view.snp_height)
        }
    }
     
    //点击屏幕
    func tapSingleDid(){
        self.scacle += 0.5
        self.box.snp_updateConstraints{ (make) -> Void in
            //放大视图(优先级最低)
            make.width.height.equalTo(100 * self.scacle).priorityLow();
        }
    }
}
 
2,带有动画效果
配合 UIView.animateWithDuration,我们可以在约束改变的时候有动画效果。 
还是以上面的样例演示,不够这次点击屏幕时橙色视图放大的时候会有过渡,而不是一下就变大。
原文:Swift - 自动布局库SnapKit的使用详解3(约束优先级,约束做动画)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    lazy var box = UIView()
     
    var scacle = 1.0
    
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //单击监听
        let tapSingle=UITapGestureRecognizer(target:self,action:#selector(tapSingleDid))
        tapSingle.numberOfTapsRequired=1
        tapSingle.numberOfTouchesRequired=1
        self.view.addGestureRecognizer(tapSingle)
         
        box.backgroundColor = UIColor.orangeColor()
        self.view.addSubview(box)
         
        box.snp_makeConstraints { (make) -> Void in
            //视图居中
            make.center.equalTo(self.view)
            //初始宽、高为100(优先级低)
            make.width.height.equalTo(100 * self.scacle).priorityLow();
            //最大尺寸不能超过屏幕
            make.width.height.lessThanOrEqualTo(self.view.snp_width)
            make.width.height.lessThanOrEqualTo(self.view.snp_height)
        }
    }
     
    //视图约束更新
    override func updateViewConstraints() {
        self.box.snp_updateConstraints{ (make) -> Void in
            //放大尺寸(优先级低)
            make.width.height.equalTo(100 * self.scacle).priorityLow();
        }
         
        super.updateViewConstraints()
    }
     
    //点击屏幕
    func tapSingleDid(){
        self.scacle += 0.5
        //告诉self.view约束需要更新
        self.view.setNeedsUpdateConstraints()
        //动画
        UIView.animateWithDuration(0.3) {
            self.view.layoutIfNeeded()
        }
    }
}


四、Swift - 自动布局库SnapKit的使用详解4(样例1:实现一个登录页面)

前面的几篇文章讲解了自动布局库SnapKit的使用方法(点击查看SnapKit的配置方法)。本文通过一个完整的样例(登录页面)来演示在实际项目中如何使用SnapKit来实现自动化布局的。
 
1,效果图如下
         原文:Swift - 自动布局库SnapKit的使用详解4(样例1:实现一个登录页面)            原文:Swift - 自动布局库SnapKit的使用详解4(样例1:实现一个登录页面)
 
2,代码讲解
(1)用户名、密码输入区域(白色区域)设置垂直居中约束,其高度是固定90,宽度自适应(距离屏幕左右侧都为15像素)
(2)用户名、密码输入框之间分割线是使用灰色背景的UIView实现,其高度是1像素,同样设置垂直居中约束。
(3)登录按钮距离上方输入区域20像素,高度固定是40,宽度同样自适应(距离屏幕左右侧都为15像素)
(4)上方标题标签据下方输入区域20像素,宽度自适应,内容居中。
(5)当键盘出现时,修改输入区域的垂直约束偏移量,使其向上移动(移动时,登陆按钮、标题标签也会同步移动)。避免在使用小屏设备时,键盘把登录框给挡住。
(6)键盘消失时,整个登录区域又会下移回复原位(上移、下移过程都有动画效果)
 
3,页面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import UIKit
import SnapKit
 
class ViewControllerUIViewControllerUITextFieldDelegate {
     
    var txtUser: UITextField//用户名输入框
    var txtPwd: UITextField//密码输入款
    var formView: UIView//登陆框视图
    var horizontalLine: UIView//分隔线
    var confirmButton:UIButton//登录按钮
    var titleLabel: UILabel//标题标签
     
    var topConstraint: Constraint//登录框距顶部距离约束
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //视图背景色
        self.view.backgroundColor = UIColor(red: 1/255, green: 170/255, blue: 235/255,
                                            alpha: 1)
         
        //登录框高度
        let formViewHeight = 90
        //登录框背景
        self.formView = UIView()
        self.formView.layer.borderWidth = 0.5
        self.formView.layer.borderColor = UIColor.lightGrayColor().CGColor
        self.formView.backgroundColor = UIColor.whiteColor()
        self.formView.layer.cornerRadius = 5
        self.view.addSubview(self.formView)
        //最常规的设置模式
        self.formView.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(15)
            make.right.equalTo(-15)
            //存储top属性
            self.topConstraint = make.centerY.equalTo(self.view).constraint
            make.height.equalTo(formViewHeight)
        }
         
        //分隔线
        self.horizontalLine =  UIView()
        self.horizontalLine.backgroundColor = UIColor.lightGrayColor()
        self.formView.addSubview(self.horizontalLine)
        self.horizontalLine.snp_makeConstraints { (make) -> Void in
            make.height.equalTo(0.5)
            make.left.equalTo(15)
            make.right.equalTo(-15)
            make.centerY.equalTo(self.formView)
        }
         
        //密码图
        let imgLock1 =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
        imgLock1.image = UIImage(named:"iconfont-user")
         
        //密码图
        let imgLock2 =  UIImageView(frame:CGRectMake(11, 11, 22, 22))
        imgLock2.image = UIImage(named:"iconfont-password")
         
        //用户名输入框
        self.txtUser = UITextField()
        self.txtUser.delegate = self
        self.txtUser.placeholder = "用户名"
        self.txtUser.tag = 100
        self.txtUser.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
        self.txtUser.leftViewMode = UITextFieldViewMode.Always
        self.txtUser.returnKeyType = UIReturnKeyType.Next
         
        //用户名输入框左侧图标
        self.txtUser.leftView!.addSubview(imgLock1)
        self.formView.addSubview(self.txtUser)
         
        //布局
        self.txtUser.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(15)
            make.right.equalTo(-15)
            make.height.equalTo(44)
            make.centerY.equalTo(0).offset(-formViewHeight/4)
        }
         
        //密码输入框
        self.txtPwd = UITextField()
        self.txtPwd.delegate = self
        self.txtPwd.placeholder = "密码"
        self.txtPwd.tag = 101
        self.txtPwd.leftView = UIView(frame:CGRectMake(0, 0, 44, 44))
        self.txtPwd.leftViewMode = UITextFieldViewMode.Always
        self.txtPwd.returnKeyType = UIReturnKeyType.Next
         
        //密码输入框左侧图标
        self.txtPwd.leftView!.addSubview(imgLock2)
        self.formView.addSubview(self.txtPwd)
         
        //布局
        self.txtPwd.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(15)
            make.right.equalTo(-15)
            make.height.equalTo(44)
            make.centerY.equalTo(0).offset(formViewHeight/4)
        }
         
        //登录按钮
        self.confirmButton = UIButton()
        self.confirmButton.setTitle("登录", forState: UIControlState.Normal)
        self.confirmButton.setTitleColor(UIColor.blackColor(),
                                         forState: UIControlState.Normal)
        self.confirmButton.layer.cornerRadius = 5
        self.confirmButton.backgroundColor = UIColor(colorLiteralRed: 1, green: 1, blue: 1,
                                                     alpha: 0.5)
        self.confirmButton.addTarget(self, action: #selector(loginConfrim),
                                     forControlEvents: .TouchUpInside)
        self.view.addSubview(self.confirmButton)
        self.confirmButton.snp_makeConstraints { (make) -> Void in
            make.left.equalTo(15)
            make.top.equalTo(self.formView.snp_bottom).offset(20)
            make.right.equalTo(-15)
            make.height.equalTo(44)
        }
         
        //标题label
        self.titleLabel = UILabel()
        self.titleLabel.text = "hangge.com"
        self.titleLabel.textColor = UIColor.whiteColor()
        self.titleLabel.font = UIFont.systemFontOfSize(36)
        self.view.addSubview(self.titleLabel)
        self.titleLabel.snp_makeConstraints { (make) -> Void in
            make.bottom.equalTo(self.formView.snp_top).offset(-20)
            make.centerX.equalTo(0)
            make.height.equalTo(44)
        }
    }
     
    //输入框获取焦点开始编辑
    func textFieldDidBeginEditing(textField:UITextField)
    {
         
        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.topConstraint?.updateOffset(-125)
            self.view.layoutIfNeeded()
        })
    }
     
    //输入框返回时操作
    func textFieldShouldReturn(textField:UITextField) -> Bool
    {
        let tag = textField.tag
        switch tag {
        case 100:
            self.txtPwd.becomeFirstResponder()
        case 101:
            loginConfrim()
        default:
            print(textField.text)
        }
        return true
    }
     
    //登录按钮点击
    func loginConfrim(){
        //收起键盘
        self.view.endEditing(true)
        //视图约束恢复初始设置
        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.topConstraint?.updateOffset(0)
            self.view.layoutIfNeeded()
        })
    }
}
源码下载:hangge_1112.zip


五、Swift - 自动布局库SnapKit的使用详解5(样例2:实现一个计算器界面)

前面演示了使用SnapKit实现一个登录页面(点击此处查看),本文再来一个稍微复杂点的样例:模仿iOS系统自带的计算器布局。(SnapKit具体配置方法可参考:Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)

1,效果图如下 
原文:Swift - 自动布局库SnapKit的使用详解5(样例2:实现一个计算器界面)

2,代码讲解
(1)首先将视图分成上下两部分,上面部分用来显示数字,下面部分是键盘区域(放置计算器按钮)。
(2)键盘区域宽高比是4:5(保证每个按钮是正方形)。
(3)按从上到下,从左往右的顺序添加每个按钮,并设置对应的约束。
(4)按钮的垂直位置约束是:下一排的按钮顶部紧跟着上一排按钮的底部。
(5)按钮的水平位置约束是:第1列按钮左侧等于页面左边缘,第4列按钮右侧等于页面右边缘。第2列按钮右侧等于页面中线位置,第3列按钮左侧等于页面中线位置。
 
3,页面代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import UIKit
import SnapKit
 
class ViewControllerUIViewController {
     
    override func viewDidLoad() {
        super.viewDidLoad()
         
        //申明区域,keyboardView是键盘区域
        let keyboardView =  UIView()
        keyboardView.backgroundColor = UIColor(red:212/255, green:213/255, blue:216/255,
                                               alpha:1)
        self.view.addSubview(keyboardView)
         
        //键盘区域约束
        keyboardView.snp_makeConstraints { (make) -> Void in
             
            make.bottom.equalTo(self.view.snp_bottom)
            make.left.right.equalTo(self.view)
            make.height.equalTo(self.view.snp_width).multipliedBy(1.25)
        }
         
        //displayView是显示区
        let displayView =  UIView()
        displayView.backgroundColor = UIColor.blackColor()
        self.view.addSubview(displayView)
         
        //显示区域约束
        displayView.snp_makeConstraints { (make) -> Void in
            make.top.equalTo(self.view.snp_top)
            make.bottom.equalTo(keyboardView.snp_top)
            make.left.right.equalTo(self.view)
        }
         
        //设置显示位置的数字为0
        let displayNum =  UILabel()
        displayNum.text = "0"
        displayNum.font = UIFont(name:"HeiTi SC", size:70)
        displayNum.textColor = UIColor.whiteColor()
        displayNum.textAlignment = .Right
        displayView.addSubview(displayNum)
         
        //数字标签约束
        displayNum.snp_makeConstraints { (make) -> Void in
            make.left.right.equalTo(displayView).offset(-10)
            make.bottom.equalTo(displayView).offset(-10)
        }
         
        //定义键盘键名称(?号是占位符,代表合并的单元格)
        let keys = ["AC","+/-","%","÷"
            ,"7","8","9","x"
            ,"4","5","6","-"
            ,"1","2","3","+"
            ,"0","?",".","="]
         
        //保存所有的按钮
        var keyViews = [UIButton]()
         
        //循环添加按钮
        for in 0..<5{
            for in 0..<4 {
                let indexOfKeys = i * 4 + j
                let key = keys[indexOfKeys]
                 
                //键样式
                let keyView =  UIButton(type:.Custom)
                keyboardView.addSubview(keyView)
                keyViews.append(keyView)
                keyView.setTitleColor(UIColor.blackColor(), forState: .Normal)
                keyView.setTitle(key, forState: .Normal)
                keyView.layer.borderWidth = 0.5
                keyView.layer.borderColor = UIColor.blackColor().CGColor
                keyView.titleLabel?.font = UIFont(name:"Arial-BoldItalicMT", size:30)
                 
                 //处理合并单元格(不用添加到界面上,也不用添加约束)
                if key == "?"{
                    keyView.removeFromSuperview()
                        continue
                }
                 
                //设置按键约束
                keyView.snp_makeConstraints { (make) -> Void in
                    //添加高度约束
                    make.height.equalTo(keyboardView.snp_height).multipliedBy(0.2)
                     
                    //添加宽度约束
                    if key == "0" {
                        //处理 0
                        make.width.equalTo(keyboardView.snp_width).multipliedBy(0.5)
                    }else {
                        //正常的单元格
                        make.width.equalTo(keyboardView.snp_width).multipliedBy(0.25)
                    }
                     
                    //添加垂直位置约束
                    if i == 0{
                        make.top.equalTo(0)
                        keyView.backgroundColor = UIColor(red:201/255, green:202/255,
                            blue:204/255, alpha:1)
                    }else{
                        make.top.equalTo(keyViews[indexOfKeys-4].snp_bottom)
                    }
                     
                    //添加水平位置约束
                    switch (j) {
                    case 0:
                        make.left.equalTo(keyboardView.snp_left)
                    case 1:
                        make.right.equalTo(keyboardView.snp_centerX)
                    case 2:
                        make.left.equalTo(keyboardView.snp_centerX)
                    case 3:
                        make.right.equalTo(keyboardView.snp_right)
                        keyView.backgroundColor = UIColor(red:249/255, green:138/255,
                            blue:17/255, alpha:1)
                    default:
                        break
                    }
                }
            }
        }
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
源码下载:hangge_1113.zip

链接:

航哥Swift

Swift - 自动布局库SnapKit的使用详解1(配置、使用方法、样例)

仿简友动态时间轴:使用Snapkit来实现UITableViewCell的动态布局

原文地址:https://www.cnblogs.com/On1Key/p/5756343.html