最近作项目时,由于iPhone6和iPhone6Plus的兼容,咱们启用了Autolayout. 之前是由于不用也能知足需求,也是由于懒,没有认真使用,只是了解过。通过一段时间的使用,作下总结,但愿给你们些帮助哈。html
之前我写过IOS自动布局之Autoresizing是关于Autoresizing的介绍,在简单的布局上比较有用,今天总结的是更强大的Autolayout.ios
本文不是从零开始入门级的介绍,主要介绍了学习过程当中遇到一些问题的解决方案,但愿给你们帮助,若是初学者请先看看苹果文档,玩玩Autolayout.git
PS: Autolayout的强大是毋庸质疑的,当你熟悉了它以后,你确定会喜欢上它,布局将会比使用frame的绝对坐标时还方便。若是尚未用Autolayout,这已是最后的时机啦,再不学就out了。github
仍是先介绍下咱们能够用哪些途径来使用Autolayout吧,这里只作介绍,具体如何使用,你们能够点击对应连接进入文档学习。app
最直观的使用就是在xib文件中使用Autolayout. 这种方式最直观,初学者建议先在xib中拖一拖,创建布局的概念。框架
这是一个第三方的很是好用的开源框架,之前我觉得Autolayout只能用xib了,不然代码量太大了,可是Masonry让用代码写Autolayout成为可能,并且很是强大,清晰好用,示例:iphone
12345678 |
UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);[view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top).with.offset(padding.top); make.left.equalTo(superview.mas_left).with.offset(padding.left); make.bottom.equalTo(superview.mas_bottom).with.offset(-padding.bottom); make.right.equalTo(superview.mas_right).with.offset(-padding.right);}]; |
这是苹果推出的一种在代码中使用Autolayout的语法,使用特定的string来建立Constraint,如[button]-[textField]
表明button和textField间隔标准间距(通常是8) Virtual Format Language 我的感受没有Masonry好理解和使用。布局
Autolayout的本质就是经过给view添加约束,系统经过这些约束来计算view的真实frame. 约束就是类NSLayoutConstraint
的实例。这里牵涉到Constraint的原理,稍做解释下,理解原理对学习老是好的。那么,什么是Constraint呢? 看下面的公式:学习
y = m ∙ x + b优化
每个NSLayoutConstraint
都表明了上面的这个关系式,其中:
x, y 表明view的attribute, attribute能够分为left right top bottom leading trailing width height centerX centerY baseline m 是倍数, 即multiplier b 常数, 即 constant
从这个公式咱们能够了解咱们在建立Constraint时,设置的值是如何工做的,好比: x表明 view1.width, y表明view2.width, m = 2, b = 0; 这个约束就表明view2的宽是view1的2倍。
从公式中也能够了解到Constraint只能表明线性关闭,不过只是布局貌似不必更复杂的关系吧。
有没有发现attribute中有了left和right, 可是还有leading和trailing. 用过的同窗会发现这两对没啥区别,为何会有这2种呢,缘由是否是世界上全部的文字都是从left到right。 若是文字是从右到左的话,leading就对应right, training就对应left了。
手动建立Constraint的API:
1234567 |
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c; |
理解了上面的公式,再看这个API是否是不同了呢。
经过分析,咱们决定采用前两种方式来进行Autolayout的开发。因此不管你是否是代码党,均可以玩转Autolayout哦。
当咱们使用Autoresizing时,运行时会自动根据autoresizingMask的特性为view添加Constraint, 咱们能够经过下面这个API来决定启用仍是关闭这一特性(NO为关闭):
1 |
- (void)setTranslatesAutoresizingMaskIntoConstraints:(BOOL)flag NS_AVAILABLE_IOS(6_0); |
这个属性在xib中默认是NO, 在不用xib时默认是YES, 也就是若是使用代码建立Constraint时,须要设置该属性为NO, Masonry
自动帮咱们作了这一操做,因此用Masonry
不须要设置改属性。
在xib中设置Constraint时,你会看到这块:
在UIView的API中也能够看到这几个方法:
1234 |
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0); |
那么这两个东西究竟是什么呢?能够这样形象的理解一下:
contentHugging: 抱住使其在“内容大小”的基础上不能继续变大 contentCompression: 撑住使其在在其“内容大小”的基础上不能继续变小
这两个属性分别能够设置水平方向和垂直方向上的,并且一个默认优先级是250, 一个默认优先级是750. 由于这两个颇有可能与其余Constraint冲突,因此优先级较低。
设置Constraint的过程其实就是作算术题的过程,这里提醒你们, xib中有Suggest Constraint的功能,可是你们不要用,特别是在学习Autolayout阶段,Suggest Constraint自动补全的Constraint通常不能直接用,除非你view不多。
若是设置Constraint来肯定一个view的frame呢,你能够里面想到: * 1. frame法,像定义frame同样定义约束,就是设置view.left view.top view.width view.height. 可是实际中不多这样用。 * 2. edge法, 设置 view.left view.top view.bottom view.right。 * 3. 居中法, 设置 centerX centerY width height.
等等方法,然而事实使用中你可能不是只有一个view,有可能有不少的view,相互直接会有不少的约束,约束一多就会容易发生逻辑冲突,这个时候就会发现Constraint优先级的做用了。
Constraint还有个属性叫priority, 即优先级,通常是0 ~ 1000之间的整数。 1000表明是必需的, 0则不会生效。理解和使用好优先级是熟练使用Autolayout所必备的。
举个栗子, UITableViewCell
会默认设置 cell.height
这个约束, 若是你像上图中设置了垂直方向上的Constraint,在IOS7上是有crash的风险的哦。下面讲缘由:
label1.top + label1.height + (label1-label2) + lable2.height +label2.bottom ≠ cell.height
若是上面不等式发生,那么就会产生Constraint冲突,在IOS8上,苹果应该作了优化,不会crash,只是在控制台会报警告,在IOS7上就会crash了。
啥,你说这些值你都提早算正确就不会出问题了? 不要太自信,还有一种东西叫“浮点值不许”。 因此最好尽可能避免这样的冲突,解决方案也很简单: 选择一个constraint下降优先级,好比把label2.bottom的优先级调到 998. 这样就解决了约束冲突的问题,当约束发生冲突时,低优先级的约束会被舍弃。
假设在同一水平方向上平行的 Label1 和 Label2。当在水平屏幕宽度不足以展现两个Label的所有内容时,怎么决定哪一个Label先展现不全呢,就是经过设置起contentCompression的水平方向上的优先级就能够解决。好比当 Label1.contentCompression < Label2.contentCompression 时, 那么Label1就会展现为 “内容…” 这种。
Autolayout看再多的教程资料不如本身动手一试,因此本文不作详细介绍,旨在分析理解和问题。 (一)就到这吧, 下一篇将会介绍 《自动适应高度Label和Cell的方案》, 《如何在ScrollView中使用Autolayout》, 《Autolayout时的动画》。