http://my.oschina.net/u/2360693/blog/481236?p={{totalPage}}

创建Xib文件

首先将Cell做好布局,调整到满意的位置和宽度,然后开始做Autolayout设定。

Autolayout操作方式有两种,一种是选择目标后,使用右下角的工具栏;另一种是直接使用右键拖拽目标,在弹出的菜单中选择限制项。当选择的目标比较小的时候,可以打开左侧的菜单,在这里做拖拽操作一样是可以的。个人感觉后者更方便一些。

开始之前,先来介绍下使用的基本工具吧。

第一个按钮是和对齐有关的,就是控制多个元素(Lable, Button等)的统一约束。例如我们需要让标题和内容按照左,就选择标题和内容元素,选择Leading Edges设置为5即可。

第二个按钮是和元素位置固定有关的限制条件,直接看图吧:

右侧能够看到当前选择元素限制条件的列表:


这里有两个参数,“Content Hugging Priority”和“Content Compression Resistance Priority”,感觉不太好理解,栈爆上找到一篇解释,讲的挺好的:Cocoa Autolayout: content hugging vs content compression resistance priority

有时候想要一个元素的间距是一个动态值,例如距离右侧至少10pt(即>=10pt),那么可以在上图中点击右侧按钮(齿轮)进入详细设置:

第三个按钮是有关清除限制条件、根据限制更新视图大小的工具。个人比较常用的是清除限制条件,有时候设置错了很麻烦,直接清除掉重新来就行了。

上面这些就是常用到的一些限制条件了。个人觉得使用右键拖拽弹出的菜单选择更方便和直观一些,因为菜单中会根据拖拽内容动态显示可用项供我们选择,菜单如图

大致就是这些了吧……

我来谈谈自己的用法。总体上是从上到下,从左到右做约束限制。在这个例子中,就是设置标题->内容->发帖人这样的顺序。

  1. 设置标题的顶部和左侧距离,以及宽度(防止超出边界)。

  2. 设置内容的顶部(距离标题)和左侧距离,以及宽度。设置最大行数。

  3. 设置发帖人的顶部和左侧距离,以及高度。

  4. 设置发帖时间的顶部和左侧距离,距离右侧间距(防止内容过长)。

  5. 关键步骤,设置发帖人距离底部距离,如果不设置这个参数,那么下面代码计算的Cell高度会永远是0。

多试一试,如果有错误或者缺少限制,XCode会有提示。它报出的错误一般都是必须修正的,但它给的自动修正建议有时并不是我们想要的(正确的),想清楚再添加。

代码部分

使用了xib制作的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

28

29

30

31

32

33

34

35

36

37

static NSString *CellIdentifier = @"CellIdentifier";

- (void)viewDidLoad

{

//注册TableView中用于复用的Cell

[self.tableView registerNib:[UINib nibWithNibName:@"BBSPostContentCell" bundle:nil]forCellReuseIdentifier:CellIdentifier];

//...

}

//关键方法,获取复用的Cell后模拟赋值,然后取得Cell高度

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

NSDictionary *dataSourceItem = [self.dataSource objectAtIndex:indexPath.row];

cell.titleLabel.text =  [dataSourceItem valueForKey:@"title"];

cell.contentLabel.text = [dataSourceItem valueForKey:@"body"];

[cell setNeedsUpdateConstraints];

[cell updateConstraintsIfNeeded];

CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

return height;

}

//在cellForRowAtIndexPath中,按照常规方法做赋值就行了

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath

{

BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

NSDictionary *dic = dataSource[indexPath.row];

cell.titleLabel.text = dic[@"title"];

cell.contentLabel.text = dic[@"body"];

return cell;

}

2014.1.2: 在测试时发现这部分的代码还存在一些性能问题(整个表视图在更新时会卡顿),我会稍后补上。

我在使用Instruments分析发现,heightForRowAtIndexPath中调用dequeueReusableCellWithIdentifier会占用很多CPU资源,因此我试着不使用registerNib方法注册复用Cell,而在代码中手动处理,类似这样:

1

2

3

4

5

6

7

BBSPostContentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

cell = [[NSBundle mainBundle] loadNibNamed:@"BBSPostContentCell" owner:self options:NULL][0];

NSLog(@"cell loadNibNamed");

} else {

NSLog(@"cell dequeueReusableCellWithIdentifier");

}

这时我发现这里的Cell调用dequeueReusableCellWithIdentifier方法总是返回nil,因此每次都是从xib中加载,从而耗费了大量的资源。问题的原因我还不清楚,目前我的解决方法是,单独生成一个Cell用于在heightForRowAtIndexPath方法中计算高度。

其次,在[tableView reloadData]和[tableView insertRowsAtIndexPaths]时,底层会将所有行高重新计算,这个会占用大量的时间,因此我试着对行高做了缓存,暂时解决了这个问题。

关于兼容性问题

由于Autolayout只能在iOS6.0以上版本使用,而根据友盟统计,目前6.0以下的用户大概还有8%左右(2013.12)。现在有两个办法解决:

  1. 哥不在乎,放弃这些用户!(好霸气=。=)把项目的部署版本修改为6.0以上即可。

  2. 咳…咳…这个嘛,用户还是有必要支持的………恩,那我们来说说这个怎么兼容。

思路很简单,我们告诉XCode,6.0以上版本使用Autolayout,以下的旧版本不要使用这个就可以了。

将原xib文件inspector中选择”Interface Builder Document”->”Build for”->”iOS 6.0 and Later”,告诉XCode,这个xib在6.0以上设备编译。

将xib文件拷贝一份副本,命名为”xxx_iOS5.xib”,在inspector中选择”Project Deployment Target”,也就是说使用项目部署目标版本(即最低版本5.0),并取消”Use Autolayout”选项。

在代码中根据系统版本加载不同的xib文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) \

([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] !=NSOrderedAscending)

#define IS_SUPPORT_AUTOLAYOUT   SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")

- (void)viewDidLoad

{

if (!IS_SUPPORT_AUTOLAYOUT) {

//for iOS 5.x

[self.tableView registerNib:[UINib nibWithNibName:@"BBSPostContentCell_iOS5" bundle:nil]forCellReuseIdentifier:CellIdentifier];

} else {

[self.tableView registerNib:[UINib nibWithNibName:@"BBSPostContentCell" bundle:nil]forCellReuseIdentifier:CellIdentifier];

}

}

最后别忘了在高度计算时,区分下代码:

1

2

3

4

5

6

7

8

9

10

11

12

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

if (IS_SUPPORT_AUTOLAYOUT) {

//Autolayout部分代码,同上

//.....

return height;

} else {

//for iOS 5.x

//为了简单起见,就直接使用固定值了,当然如果你要自己为iOS5用户手动计算动态高度,也是可以的。

return 81;

}

}

完成了!

2013的最后一篇文章,元旦快乐! 

原创文章,采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
转载请注明:转载自 Tony's blog,原文网址:http://itony.me/381.html

使用Autolayout xib实现动态高度的TableViewCell的更多相关文章

  1. iOS开发——使用Autolayout生成动态高度的TableViewCell单元格

    步骤一.TableViewCell中使用Autolayout 要点:Cell的高度必须在Constraints中指明,但不能定死,需要让内部由内容决定高度的View决定动态高度. 如UILabel设置 ...

  2. AutoLayout处理UITableView动态高度

    我们经常会遇到UITableViewCell的高度要跟随内容而调整,在未引入AutoLayout之前,我们使用以下方法计算Label高度,然后heightForRowAtIndexPath中返回计算的 ...

  3. AutoLayout深入浅出五[UITableView动态高度]

    本文转载至 http://grayluo.github.io//WeiFocusIo/autolayout/2015/02/01/autolayout5/ 我们经常会遇到UITableViewCell ...

  4. soui中,列表控件动态高度的使用注意

    1.listview的模板template中,需要增加defHeight属性,即默认高度,同时,不能出现itemHeight属性,否则动态高度会失效 2.数据适配器中,重写getViewDesired ...

  5. swift 版本 UItableViewCell的动态高度补足

    用swift的朋友们很多都是从ios8开发了, 其中针对table cell高度自动计算的 UITableViewAutomaticDimension 异常好用,但好像只对uilabel对象有效    ...

  6. iOS 界面 之 EALayout 无需反复编译,可视化实时界面,告别Storyboard AutoLayout Xib等等烦人的工具

    http://blog.csdn.net/fatherhui iOS开发,EALayout 无需反复编译,可视化实时界面,告别Storyboard AutoLayout Xib等等烦人的工具 EALa ...

  7. css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位

    css中height 100vh的应用场景,动态高度百分比布局,浏览器视区大小单位 height:100vh 一些只能vw, vh才能完成的应用场景: 1. 场景之:元素的尺寸限制 vw vh 主要是 ...

  8. autoHeight # 动态高度添加 用 window.addEventListener('resize', function () {

    动态高度添加 用 window.addEventListener('resize', function () { mounted () { this.init() window.addEventLis ...

  9. CSS 奇技淫巧:动态高度过渡动画

    这个问题源自于掘金上的一个留言,一个朋友问到,为什么我下面这段代码的高度过渡动画失效了? 伪代码大概是这样: { height: unset; transition: all 0.3s linear; ...

随机推荐

  1. 【WP8】扩展CM的INavigationService方法

    CM支持通过ViewModel进行导航,并通过支持参数传递,但是内部只是通过反射的方式构造Uri的参数进行导航,所以只支持简单类型的参数传递,下面对其进行扩展,在页面导航时支持复杂类型的参数传递,并扩 ...

  2. MathType调整矩阵分隔线粗细的方法

    矩阵是线性代数的重要的组成部分,对于矩阵的计算,一般会先找一些规律再进行计算这样会更加方便.对于比较复杂的矩阵,在寻找规律时经常会将矩阵进行分割,我们将这种矩阵称为分块矩阵.有时为了表示矩阵的这种分块 ...

  3. VMware12多台虚拟机上网设置

    1.根据镜像安装好linux系统, 2.  把网络适配器移除后,重新添加试试 3. 当按照上述配置后还是无法上网,把VMnet0 桥接模式的自动 ,这里重新点击下自动设置(其实没有做到自动配置) 4. ...

  4. Golang 在 Mac、Linux、Windows 交叉编译

    https://blog.csdn.net/panshiqu/article/details/53788067

  5. kendo-ui的MVVM模式

    摘要: MVVM(Model View ViewModel)是一种帮助开发者将数据从模型分离的设计模式.MVVM的ViewModel负责将数据对象从模型中分离出来,通过这种方式数据就很容易控制数据如何 ...

  6. python使用dbutils的PooledDB连接池,操作数据库

    1.使用dbutils的PooledDB连接池,操作数据库. 这样就不需要每次执行sql后都关闭数据库连接,频繁的创建连接,消耗时间 2.如果是使用一个连接一直不关闭,多线程下,插入超长字符串到数据库 ...

  7. JAVA内存泄露分析及解决

    一,问题产生     项目采用Tomcat6.0为服务器,数据库为mysql5.1,数据库持久层为hibernate3.0,以springMVC3.0为框架,项目开发完成后,上线前夕进行稳定性拷机,测 ...

  8. MinGW 是什么

    3.1:MinGW 是什么? MinGW 提供了一套简单方便的Windows下的基于GCC 程序开发环境.MinGW 收集了一系列免费的Windows 使用的头文件和库文件:同时整合了GNU ( ht ...

  9. mongodb int字段的一个小坑

    在使用 php mongodb 搜索时,如果字段类型用 int,则使用 php 搜索时一定要把数值转换成整型来搜索,用字符串类型的数字搜索是没有结果的!!!! $condition = ['membe ...

  10. FTP匿名访问修复方法

    window2003 window2008