iOS autoLayout

一、autoLayout出现

iOS6开始,苹果推出了autoLayout,当时苹果最新手机是iphone5,此时苹果手机只有两种屏幕,3.5英寸和4.0英寸,两种屏幕的宽是一样的,只有高不同,适配成本不高,由于autoLayout有一定的学习成本,所有直到iphone6和iphone6Plus问世之前,autoLayout的使用是不多的。

二、自动布局和传统布局的不同

传统布局思路中,一个view在什么位置,有多大,直接写清楚它的坐标位置和宽高就可以了。在autoLayout中提供了相对的概念,一个view的位置和大小,是相对于父视图或者同级的兄弟视图的位置决定的,决定它们的东西叫约束(NSLayoutConstraint)。

三、什么时候用autoLayout

想用的时候…
习惯了传统布局的程序员在效率上并不会比autolayout慢,但是熟练使用了autoLayout之后,在信息比较多,尺寸动态不定的界面中,应该会更有效率。比如说现在我们的app就没有使用autoLayout,但是并没有觉得效率不高。

四、autoLayout使用方式

这里不包括xib里的使用方式,只说代码的

1.使用原生api为每一个约束创建NSLayoutConstraint
API为:

public convenience init(item view1: AnyObject, attribute attr1: NSLayoutAttribute, relatedBy relation: NSLayoutRelation, toItem view2: AnyObject?, attribute attr2: NSLayoutAttribute, multiplier: CGFloat, constant c: CGFloat)

参数解释:
view1 想要添加约束的视图

attr1 想要添加约束的方向\宽高

relation 与约束值的关系(大于,等于还是小于)

view2 被参照对象

attr2 被参照对象所被参照的方向,如顶部,左边,右边等等

multiplier 传入想要的间距倍数关系

c 传入最终的差值

例如:

let viewOneLeftConstraint = NSLayoutConstraint(item: viewOne, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: .Left, multiplier: 1.0, constant:40)   

意思是viewOne这个视图的左边距离view这个视图的左边40

用这种方法比较累赘,需要为每一个约束生成一个NSLayoutConstraint的实例,一个视图需要好几个约束才能确定,代码量比较大

2.苹果推出的VFL(Visual Format Language)语言,其实就是一种规范。它的出现就是为了减轻API带来的繁琐。
API为:

public class func constraintsWithVisualFormat(format: String, options opts: NSLayoutFormatOptions, metrics: [String : AnyObject]?, views: [String : AnyObject]) -> [NSLayoutConstraint]

参数解释:
format 传入固定格式构成的字符串,用来表达想要添加的约束

opts 对齐方式

metrics 一般传入以间距为KEY的字典,如: @{ @”margin”:@20},KEY要与format参数里所填写的“margin”相同

views 传入约束中提到的View

return 返回约束的数组

例如:

let viewDic = ["viewOne" : viewOne, "viewTwo" : viewTwo, "viewThree" : viewThree]
let viewsHConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[viewOne]-padding-[viewTwo(viewOne)]-padding-[viewThree(viewTwo)]-|", options: NSLayoutFormatOptions(rawValue:0), metrics: ["padding" : 10], views: viewDic)

意思是viewOne的右边距离viewTwo的左边10个像素,viewTwo的右边距离viewThree的左边10个像素,viewOne的左边距离它的superView20个像素,viewThree的右边距离它的superView20个像素

总结一下这个语法。

功能        表达式

水平方向        H:

垂直方向        V:

Views         [view]

SuperView      |

关系         >=,==,<=

空间,间隙       -

优先级        @value

这种方法比第一种方法的代码要简洁,但是VFL使用需要一定的成本,而且都是字符串容易出错。

3.三方开源库SnapKit(swift) Masonry(OC)
这两个库是同一拨大神写的,SnapKit用在swift上,支持iOS7.0,Masonry用在oc上,支持iOS6.0,使用是非常相似的。它们提供了一个行云流水的链式语法。这里主要讲一下SnapKit在swift上的使用。
先来说明一个方法

func snp_makeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void

这个方法就是我们为视图添加约束的主要方法,对应的还有更新约束snp_updateConstraints,重做约束snp_makeConstraints(会把之前的约束删除,添加新的)
以一个小李子来说明,添加一个view,这个view的每个边都距离它的父视图20像素。

let box = UIView()
superview.addSubview(box)
box.snp_makeConstraints { (make) -> Void in
make.top.equalTo(superview).offset(20)
make.left.equalTo(superview).offset(20)
make.bottom.equalTo(superview).offset(-20)
make.right.equalTo(superview).offset(-20)
}

貌似和用系统提供的并没有减少多少的代码量,简化一下就不一样了

let box = UIView()
superview.addSubview(box)
box.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(superview).inset(UIEdgeInsetsMake(20, 20, 20, 20))
}    

SnapKit中的视图属性和使用appleAPI的NSLayoutAttribute的对应关系如下:

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

优先级:

  • .priority: 允许您指定一个确切的优先级
  • .priorityHigh: 高优先级 等价于 UILayoutPriority.DefaultHigh
  • .priorityMedium:中优先级
  • priorityLow:低优先级 UILayoutPriority.DefaultLow

例如:

make.left.greaterThanOrEqualTo(label.snp_left).priorityLow()
make.top.equalTo(label.snp_top).priority(600)    

SnapKit提供了一些便利的方法来同时创建约束

  • edges

    // make top, left, bottom, right equal view2
    make.edges.equalTo(view2);

    // make top = superview.top + 5, left = superview.left + 10,
    // bottom = superview.bottom - 15, right = superview.right - 20
    make.edges.equalTo(superview).inset(UIEdgeInsetsMake(5, 10, 15, 20))

  • size

    // make width and height greater than or equal to titleLabel
    make.size.greaterThanOrEqualTo(titleLabel)
    // make width = superview.width + 100, height = superview.height - 50
    make.size.equalTo(superview).offset(CGSizeMake(100, -50))

  • center

    // make centerX and centerY = button1
    make.center.equalTo(button1)
    // make centerX = superview.centerX - 5, centerY = superview.centerY + 10
    make.center.equalTo(superview).offset(CGPointMake(-5, 10))

还可以使用链式属性来增加代码的可读性

// All edges but the top should equal those of the superview
make.left.right.bottom.equalTo(superview)
make.top.equalTo(otherView)   

学会了上面的基本操作,就可以愉快的使用SnapKit了

几种方式的简单示例autoLayoutDemo

你可能感兴趣的:(iOS autoLayout)