iOS 8 自适应 Cell
在使用 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相关推荐
- iOS tableViewCell自适应高度 第三发类库
转自:http://www.cnblogs.com/qianLL/p/5393331.html 在github中有许多大牛封装好的第三发类库,其中有个自适应cell高度的类库 下载地址:https:/ ...
- ios 获取html的高度,iOS Webview自适应实际内容高度的4种方法详解
//第一种方法 - (void)webViewDidFinishLoad:(UIWebView *)webView { CGFloat webViewHeight=[webView.scrollVie ...
- 可变cell,自适应cell,理解iOS 8中的Self Sizing Cells和Dynamic Type
在iOS 8中,苹果引入了UITableView的一项新功能--Self Sizing Cells,对于不少开发者来说这是新SDK中一项非常有用的新功能.在iOS 8之前,如果想在表视图中展示可变高度 ...
- IOS TableView的Cell高度自适应,UILabel自动换行适应
需求: 1.表格里的UILable要求自动换行 2.创建的tableViewCell的高度会自动适应内容的高度 一.用xcode构建项目,创建一个有tableView的视图,用纯代码的形式实现: 1. ...
- iOS中 UITableViewCell cell划线那些事 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 在开发中经常遇到cell分割线显示不全或者想自定义线的宽高等; 最近总结了一下,希望帮到大家: 1.不想划线怎么办? Table ...
- IOS Table中Cell的重用reuse机制分析
2019独角兽企业重金招聘Python工程师标准>>> 解决代码: - (UITableViewCell *)tableView:(UITableView *)tableView c ...
- IOS UITextView自适应高度
LOFTER app需要实现了一个类似iPhone短信输入框的功能,它的功能其实蛮简单,就是:[UITextView的高度随着内容高度的变化而变化].实现思路应该是: 在UITextView的text ...
- iOS-关于cell的重叠问题
记得很早之前遇到过一个问题,关于cell的重叠问题,现在回顾总结一下. iOS中tableview的cell显示是会消耗内存的,如果要显示无数个cell,不可能把每个cell都存储下来,为了解决这个问 ...
- iOS 按钮、Cell暴力点击触发多次响应的问题研究
在app使用的过程中,由于网络差,手机卡顿等问题,用户在不经意的时候可能多次操作,造成多次请求.或者页面多次push等,给用户带来了不好的体验,那么如何解决相关的问题呢?本文介绍几种解决办法,在某种程 ...
- iOS StoryBoard自适应布局
原文地址:点击打开链接 通用的Storyboard 通用的stroyboard文件是通向自适应布局光明大道的第一步.在一个storyboard文件中适配iPad和iPhone的布局在iOS8中已不再是 ...
最新文章
- 放大 旋转 css3,CSS3详解:transform 的旋转、旋转放大、放大、移动
- python自然语言处理一作者书
- netflix feign概述
- 2095 : 我只看看不写题(贪心)
- 工业以太网交换机的优势以及注意事项介绍
- Java IdentityHashMap putAll()方法与示例
- php scandir sftp,CentOS 下使用SFTP实现网站自动生成FTP账号,实现Chroot功能
- 今天心情好,一起探讨下《送给大家的200兆SVN代码服务器》怎么管理我们的VS代码?...
- 给云服务器上传文件,如何给云服务器上传文件
- linux adb工具 终极总结
- 开源大数据周刊-第90期
- 三维计算机软件图,三维cad看图
- [FROM WOJ]#4479 长跑
- 京东方高级副总裁姜幸群:AIoT技术赋能企业物联网转型
- 输入年月日获取农历日期
- IOL2020中国初选第一题题解
- Microbiome:40年施肥处理后固氮菌及氮固定受抑制
- 计算机管理哪个是主板驱动,请问一下这里面哪个是主板驱动?
- weui 可移动悬浮按钮
- FANUC机器人Config系统配置中各项参数的功能描述及设定