ISO 8 自适应cell

原文网址: http://www.cocoachina.com/ios/20141218/10687.html

在使用 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 帮我们完成所有的工作吧。

时间: 2024-10-08 15:56:36

ISO 8 自适应cell的相关文章

iOS 8:【转】iOS 8 自适应 Cell

源地址:http://vit0.com/blog/2014/11/13/ios-8-zi-shi-ying-cell/ 在使用 table view 的时侯经常会遇到这样的需求:table view 的 cell 中的内容是动态的,导致在开发的时候不知道一个 cell 的高度具体是多少,所以需要提供一个计算 cell 高度的算法,在每次加载到这个 cell 的时候计算出 cell 真正的高度. 在 iOS 8 之前 没有使用 Autolayout 的情况下,需要实现 table view del

iOS 8 自适应 Cell

在使用 table view 的时侯经常会遇到这样的需求:table view 的 cell 中的内容是动态的,导致在开发的时候不知道一个 cell 的高度具体是多少,所以需要提供一个计算 cell 高度的算法,在每次加载到这个 cell 的时候计算出 cell 真正的高度. 在 iOS 8 之前 没有使用 Autolayout 的情况下,需要实现 table view delegate 的 tableView(tableView: UITableView, heightForRowAtInde

tableview 使用visual format language自适应cell宽高,和横竖屏

再也不用担心,如何做适配了. 使用苹果官方提供的适配方案当然是最正宗的,比第三房框架可控. 可以适配各种屏幕尺寸,以及横竖屏,欢迎有独特简介的极客们,提出宝贵意见 开发过程中,时常会遇到cell自适应高度与横屏下的宽度,传统的做法要么是手动计算frame,要么就是使用xib. 第一种方式,工作量是巨大的(相信很多人深有体会). 第二种方式,对于协同开发和有些不用xib公司来说,有些可望不可及. 第三种方式,手写constraints.手写过的猿猿们一定体会到会有多少行代码. 其实还有一种看起来不

根据展示文字自适应 cell 高度,实现点击cell的伸缩扩展

1.要根据展示的文字计算cell的高度, 再此给NSString写的延展的方法, 以此获取展示文字的高度 2.在自定义的cell中 声明属性和定义方法 注:在cell上初始化子控件,最好用代码写, 不知为何用storyBoard初始化的不能重置其frame 3.在ViewController 中

自适应Cell

// //  ViewController.m //  04-自适应cell // //  Created by ?? on 15/5/22. //  Copyright (c) 2015年 sczy. All rights reserved. // #import "ViewController.h" #import "JWStatus.h" #import "JWTableViewCell.h" #import "JWStatusF

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

在iOS 8中,苹果引入了UITableView的一项新功能--Self Sizing Cells,对于不少开发者来说这是新SDK中一项非常有用的新功能.在iOS 8之前,如果想在表视图中展示可变高度的动态内容时,你需要手动计算行高,而Self Sizing Cells为展示动态内容提供了一个解决方案.以下是你使用Self Sizing Cells时需要注意的事项: 1.为原型单元格定义Auto Layout约束 2.指定表视图的estimatedRowHeight 3.将表视图的rowHeig

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

转自:http://www.cnblogs.com/qianLL/p/5393331.html 在github中有许多大牛封装好的第三发类库,其中有个自适应cell高度的类库 下载地址:https://github.com/gsdios/SDAutoLayout model类 commentsModel #import "JSONModel.h" #import "getCommentData.h" @interface commentsModel : JSONMo

iOS 8:【转】iOS UITextView 输入内容实时更新 cell 的高度

源地址:http://vit0.com/blog/2014/12/25/ios-textview-in-cell/ 这篇文章介绍了在一个动态数据的 table view 中,cell 根据 text view 内容的输入实时改变 cell 和 table view 的高度.自动计算 cell 高度的功能使用 iOS 8 才支持的自适应 cell,如果你还不知道 iOS 8 自适应 cell,可以参看这篇文章:iOS 8 自适应 Cell 先上图,我们最终要实现的效果是这样的: 图 1:实时更新

iOS UITextView 输入内容实时更新cell的高度

先上图,我们最终要实现的效果是这样的:可参考(http://www.cocoachina.com/ios/20141226/10778.html) 图 1:实时更新 cell 高度 实现上面效果的基本原理是: 在 cell 中设置好 text view 的 autolayout,让 cell 可以根据内容自适应大小 text view 中输入内容,根据内容更新 textView 的高度 调用 tableView 的 beginUpdates 和 endUpdates,重新计算 cell 的高度