在使用 table view 的时侯经常会遇到这样的需求:table view 的 cell 中的内容是动态的,导致在开发的时候不知道一个 cell 的高度具体是多少,所以需要提供一个计算 cell 高度的算法,在每次加载到这个 cell 的时候计算出 cell 真正的高度。

在 iOS 8 之前

没有使用 Autolayout 的情况下,需要实现 table view delegate 的 tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 方法,在这个方法中计算并返回 cell 的高度。比如,我有一个可以显示任意行数的纯文本 cell,计算 cell 的代码可以是这样:

1
2
3
4
5
6
7
8
9
10
11
12
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    let content = self.datas[indexPath.row] as String
    let padding: CGFloat = 20
    let width = tableView.frame.size.width - padding * 2;
    let size = CGSizeMake(width, CGFloat.max)
    let attributes = [NSFontAttributeName: UIFont(name: "Helvetica", size: 14)!]
    let frame = content.boundingRectWithSize(size,
        options: NSStringDrawingOptions.UsesLineFragmentOrigin,
        attributes: attributes,
        context: nil)
    return frame.size.height+1;
}

上面的代码是一个最简单的例子,这个例子看起来好像没有什么问题。但是通过查看这个 delegate 方法的文档后,可以知道,在每次 reload tableview 的时候,程序会先计算出每一个 cell 的高度,等所有高度计算完毕,确定了 tableview 的总的高度后,才开始渲染视图并显示在屏幕上。这意味着在显示 table view 之前需要执行一堆的计算,并且这是在主线程中进行的,如果计算量太大程序就很有可能出现卡顿感。比如: table view 的数据有上千条,或者计算高度的代码中还要先获取图片再根据图片计算高度,这些操作都是非常慢的。

如果在 cell 中使用了 autolayout,在计算 cell 高度时会更麻烦。有兴趣的可以看这里有篇关于如何在 autolayout 下动态计算高度的文章。

为什么不能等滚动到某个 cell 的时候,再调用计算这个 cell 高度的 delegate 呢?原因是 tableview 需要获得它的内容的总高度,用这个高度去确定滚动条的大小等。直到 iOS 7 UITableViewDelegate中添加了新的 API:

1
tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

这个方法用于返回一个 cell 的预估高度,如果在程序中实现了这个方法,tableview 首次加载的时候就不会调用heightForRowAtIndexPath 方法,而是用 estimatedHeightForRowAtIndexPath 返回的预估高度计算 tableview 的总高度,然后 tableview 就可以显示出来了,等到 cell 可见的时候,再去调用heightForRowAtIndexPath 获取 cell 的正确高度。

通过使用estimatedHeightForRowAtIndexPath 这个 Delegate 方法,解决了首次加载 table view 出现的性能问题。但还有一个麻烦的问题,就是在 cell 没有被加载的时候计算 cell 的高度,上面给出的代码中,仅仅是计算一个 NSString 的高度,就需要不少代码了。这种计算实际上是必须的,然而在 iOS 8 开始,你可能可以不用再写这些烦人的计算代码了!

iOS 8 的魔法

在 iOS 8 中,self size cell 提供了这样一种机制:cell 如果有一个确定的宽度/高度,autolayout 会自动根据 cell 中的内容计算出对应的高度/宽度。

TableView 中的 cell 自适应

要让 table view 的 cell 自适应内容,有几个要点:

1.设置的 AutoLayout 约束必须让 cell 的 contentView 知道如何自动延展。关键点是 contentView 的 4 个边都要设置连接到内容的约束,并且内容是会动态改变尺寸的。

2.UITableView 的 rowHeight 的值要设置为 UITableViewAutomaticDimension

3.和 iOS 7 一样,可以实现 estimatedHeightForRowAtIndexPath 方法提升 table view 的第一次加载速度。

4.任何时候 cell 的 intrinsicContentSize 改变了(比如 table view 的宽度变了),都必须重新加载 table view 以更新 cell。

例子

在 Xcode 中新建一个项目,在 storyboard 中创建一个 UITableViewController 的 IB,创建一个如下样子的 cell:

这个 cell 中有 3 个元素,其中 imageView 的 autoLayout 约束为:

imageView 左边离 contentView 左边 0

imageView 上边离 contentView 上边 0

imageView 的 width 和 height 为 80

imageView 下边离 contentView 下边大于等于 0(为了防止内容太少,导致 cell 高度小于图片高度)

titleLabel 的 autoLayout 约束为:

titleLabel 左边离 imageView 右边 8

titleLabel 上边和 imageView 上边在同一只线上

titleLabel 右边离 contentView 右边 0

titleLabel 下边离 description 上边 8

titleLabel 的高度小于等于 22,优先级为 250

descriptionLabel 的约束为:

descriptionLabel 左边和 titleLabel 左边在同一直线上

descriptionLabel 上边里 titleLabel 8

descriptionLabel 下边里 contentView 下边 0

descriptionLabel 右边离 contentView 右边 0

然后在这个 IB 对应的 UITableViewController 中加载一些数据进去,显示效果如图:

实现这个效果,我除了设置了 autoLayout,还设置了 tableView 的 rowHeight = UITableViewAutomaticDimension,然后就是这样了。一点计算 cell 高度的代码都没有!!我连 heightForRowAtIndexPath都不用实现,真的是….爽出味啊!所以如果已经在开发 iOS 8 Only 的应用了一定要用autolayout,把烦人的计算交给 autolayout 去吧。

CollectionView 中的 cell 自适应

在 collection view 中也能让 cell 自适应内容大小,如果 UICollectionView 的 layout 是一个 UICollectionViewFlowLayout,只需要将 layout.itemSize = ... 改成 layout.estimatedItemSize = ...。 只要设置了 layout 的 estimatedItemSize,collection view 就会根据 cell 里面的 autolayout 约束去确定cell 的大小。

原理:

1.collection view 根据 layout 的 estimatedItemSize 算出估计的 contentSize,有了 contentSize collection view 就开始显示

2.collection view 在显示的过程中,即将被显示的 cell 根据 autolayout 的约束算出自适应内容的 size

3.layout 从 collection view 里获取更新过的 size attribute

4.layout 返回最终的 size attribute 给 collection view

5.collection 使用这个最终的 size attribute 展示 cell

总结

这次 iOS 8 的发布对 UI 开发来说是越来方便了,很多以前需要写大量计算的代码现在都可以通过拖拖 IB 上的 UI 控件就可以实现了,当然首先你要会 autolayout。 如果很幸运的在开发 iOS 8 only 的应用,真的可以删除heightForRowAtIndexPath中那些繁重的计算代码了!让 autolayout 帮我们完成所有的工作吧。

转载于:https://www.cnblogs.com/56ik/p/5135991.html

iOS 8 自适应 Cell相关推荐

  1. iOS tableViewCell自适应高度 第三发类库

    转自:http://www.cnblogs.com/qianLL/p/5393331.html 在github中有许多大牛封装好的第三发类库,其中有个自适应cell高度的类库 下载地址:https:/ ...

  2. ios 获取html的高度,iOS Webview自适应实际内容高度的4种方法详解

    //第一种方法 - (void)webViewDidFinishLoad:(UIWebView *)webView { CGFloat webViewHeight=[webView.scrollVie ...

  3. 可变cell,自适应cell,理解iOS 8中的Self Sizing Cells和Dynamic Type

    在iOS 8中,苹果引入了UITableView的一项新功能--Self Sizing Cells,对于不少开发者来说这是新SDK中一项非常有用的新功能.在iOS 8之前,如果想在表视图中展示可变高度 ...

  4. IOS TableView的Cell高度自适应,UILabel自动换行适应

    需求: 1.表格里的UILable要求自动换行 2.创建的tableViewCell的高度会自动适应内容的高度 一.用xcode构建项目,创建一个有tableView的视图,用纯代码的形式实现: 1. ...

  5. iOS中 UITableViewCell cell划线那些事 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang 在开发中经常遇到cell分割线显示不全或者想自定义线的宽高等; 最近总结了一下,希望帮到大家: 1.不想划线怎么办? Table ...

  6. IOS Table中Cell的重用reuse机制分析

    2019独角兽企业重金招聘Python工程师标准>>> 解决代码: - (UITableViewCell *)tableView:(UITableView *)tableView c ...

  7. IOS UITextView自适应高度

    LOFTER app需要实现了一个类似iPhone短信输入框的功能,它的功能其实蛮简单,就是:[UITextView的高度随着内容高度的变化而变化].实现思路应该是: 在UITextView的text ...

  8. iOS-关于cell的重叠问题

    记得很早之前遇到过一个问题,关于cell的重叠问题,现在回顾总结一下. iOS中tableview的cell显示是会消耗内存的,如果要显示无数个cell,不可能把每个cell都存储下来,为了解决这个问 ...

  9. iOS 按钮、Cell暴力点击触发多次响应的问题研究

    在app使用的过程中,由于网络差,手机卡顿等问题,用户在不经意的时候可能多次操作,造成多次请求.或者页面多次push等,给用户带来了不好的体验,那么如何解决相关的问题呢?本文介绍几种解决办法,在某种程 ...

  10. iOS StoryBoard自适应布局

    原文地址:点击打开链接 通用的Storyboard 通用的stroyboard文件是通向自适应布局光明大道的第一步.在一个storyboard文件中适配iPad和iPhone的布局在iOS8中已不再是 ...

最新文章

  1. 放大 旋转 css3,CSS3详解:transform 的旋转、旋转放大、放大、移动
  2. python自然语言处理一作者书
  3. netflix feign概述
  4. 2095 : 我只看看不写题(贪心)
  5. 工业以太网交换机的优势以及注意事项介绍
  6. Java IdentityHashMap putAll()方法与示例
  7. php scandir sftp,CentOS 下使用SFTP实现网站自动生成FTP账号,实现Chroot功能
  8. 今天心情好,一起探讨下《送给大家的200兆SVN代码服务器》怎么管理我们的VS代码?...
  9. 给云服务器上传文件,如何给云服务器上传文件
  10. linux adb工具 终极总结
  11. 开源大数据周刊-第90期
  12. 三维计算机软件图,三维cad看图
  13. [FROM WOJ]#4479 长跑
  14. 京东方高级副总裁姜幸群:AIoT技术赋能企业物联网转型
  15. 输入年月日获取农历日期
  16. IOL2020中国初选第一题题解
  17. Microbiome:40年施肥处理后固氮菌及氮固定受抑制
  18. 计算机管理哪个是主板驱动,请问一下这里面哪个是主板驱动?
  19. weui 可移动悬浮按钮
  20. FANUC机器人Config系统配置中各项参数的功能描述及设定

热门文章

  1. 基于VS2015的C#的GDAl环境配置
  2. 机器学习笔记0_学习资料整理
  3. arcpy 实现新增字段合并字段
  4. ArcGIS 计算挖填方区域和挖填方量
  5. 遥感学习教学课件分享
  6. 利用composer搭建PHP框架(五.自动加载)
  7. 服务器iis限制ip访问网站吗,利用IIS实现网站后台IP登录限制
  8. Spring StringUtils#cleanPath method 浅析
  9. C++总结学习(一)
  10. python面向对象——类(上)