Autolayout小结(二)
在Autolayout小结(一)中介绍了在Autolayout学习中一些基本的注意点,本文会针对一些布局上常见的问题进行分析。
- 如何自动适应cell的高度
- 如何在ScrollView中使用Autolayout
- 使用Autolayout做动画
- Autolayout在IOS6上的坑
1. 如何自动适应cell的高度
在IOS的布局中,计算和适应cell的高度是个经典的问题, 在frame时代,我们都知道用sizeWithFont:
先计算出文字的高度,然后通过计算得出cell的高度,然后赋予heightForRow:
。
那在Autolayout时代如何计算cell的高度呢?因为sizeWithFont:方法已经不太实用了。其实Autolayout不但更简单,还可以不用写过多的计算代码达到自适应高度。
理论上是可以通过已知的完整的Constraints和view的属性来计算高度的,我们可以通过systemLayoutSizeFittingSize:
方法来获取计算出来cell的size,我们知道cell的高度需要在tableView的代理方法tableView:heightForRowAtIndexPath:
中实现的,那么我们考虑从以下两点来做:
- 通过创建一个额外的cell专门用来计算其高度
- 因为计算需要布局,所以尽量让其只计算一次,计算完可以将高度保存起来
基于这两个要点,我们可以尝试如下(伪代码):
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 |
|
经过测试,工作良好,在体会到这点好处之后就发现Autolayout的好处了,它其实是让布局变得简单了。
在完成这个自动适应高度的设计过程中要注意几点:
cell中的多行UILabel,如果其width不是固定的话(比如屏幕尺寸不同,width不同),要手动设置其
preferredMaxLayoutWidth
。 因为计算UILabel的intrinsicContentSize
需要预先确定其width才行。要保证垂直方向上的Constraints理论上可以计算出cell的高度,另:最好调低其中一个Constraint的优先级,避免约束发生冲突
tableView的
dequeueReusableCellWithIdentifier
取出来的cell如果未用于tableView, 那么它就leak了. 因此用于计算高度的cell不要从此方法获取。
2. 如何在scrollView中使用Autolayout
scrollView比较特殊,因为它有个contentSize的属性。那么在遇到scrollView时,怎么使用Autolayout呢。其实关键点就一点:
ScrollView的contentSize的大小是由其subview的constraints来决定的。
知道这一点其实就够了,那么基于这个特性,在应用的时候要注意哪些呢?
- 完全依赖scrollView来计算subview的坐标的Constraints设法不行了,计算条件互相依赖的,常见的如left+right+top+bottom不行了。
- 要保证contentSize可以通过subview的constraints能够计算出来。
举个栗子:
1 2 3 4 5 6 7 8 |
|
例子中如果scrollView的size是(100x100), 那么contentSize即为(400x100)
3. Autolayout时的动画
在使用Autolayout时,动画的使用和以前也不同了,以前我们是修改frame,现在我们可以通过修改Constraints, 然后在动画时layoutIfNeeded
就行了。
1 2 3 |
|
Autolayout有时在动画时候会很方便,因为View之间的坐标是相互影响的,在传统frame中,如果改变一个view的frame,那么可能你要更改很多view的frame,才能让页面显得和谐。在Autolayout中可能只需要修改一个Constraint就可以了,在做动画时会很方便。
4. Autolayout在IOS6上的坑
虽然Autolayout非常强大,但是在刚出现的版本IOS6上,还是有一些坑的。在IOS6上你会发现在某些系统控件上如: UITableViewCell
, UITableView
等view上直接添加Constraints会crash。 冲突的Constraints会直接导致crash等。
在strackoverflow有回答上说明了为什么UITableViewCell
等部分系统控件上添加Constraints会crash, 即UITableViewCell
等部分控件的layoutSubviews
里面没有执行[super layoutSubviews]
。
所以想要使用Autolayout的同学们,如果你要兼容IOS6的话,有些问题还是要重视的,需要充分的测试哦。