iOS7和iOS8下的自适应cell

转载文章,纯粹为知识分享

我们开发中,在使用UITableView的时候经常会遇到这样的需求:table view的cell中的内容是动态的。于是我们就在table view的代理中手动去计算cell中的内容高度。这样做有两个问题:

计算代码冗长、复杂。

每次 reload tableview 的时候,系统会先计算出每一个 cell 的高度,等所有高度计算完毕,确定了 tableview 的contentSize后,才开始渲染视图并显示在屏幕上。如果数据比较多,就会感受到非常明显的卡顿。

所以,我们应该寻找其他的解决方案。如果你的项目只支持iOS8及以上,那么恭喜你,你只用简单的几步就可以实现自适应cell了。如果是iOS7也没关系,后面我也会讲到,如何在iOS下实现自适应cell。

在讲具体的实现之前,必须得说一下iOS7中新增的一个API:

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;

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

通过实现这个代理方法,解决了首次加载 table view 出现的性能问题,但是并没有让我们从复杂的计算中解脱出来。下面我会通过例子来讲解一下在iOS7和iOS8中自适应cell的实现。

iOS8的自适应cell

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

设置的AutoLayout约束必须让 cell 的contentView知道如何自动伸展。关键点是contentView的 4 个边都要设置连接到内容的约束,并且内容是会动态改变尺寸的。其实只要记住,我们在设置约束时只要能让contentView能被内容撑起来就可以了。

UITableView 的rowHeight的值要设置为UITableViewAutomaticDimension。

和 iOS 7 一样,可以实现 estimatedHeightForRowAtIndexPath 代理方法提升 table view 的第一次加载速度。也可以直接这样:self.tableView.estimatedRowHeight =  60。

好了咱们来直接上代码:

在 Xcode 中新建一个项目,设置好tableView后,自定义一个UITableViewCell:

屏幕快照 2016-02-24 上午10.25.12.png

创建好之后是这样的:

屏幕快照 2016-02-24 上午10.35.26.png

下面来看一下约束,这个是决定你的cell能否自适应的关键。

UIImageView约束如下:

左边距离contentView左边15

顶部距离contentView顶部8

width和height为 40

底部距离contentView底部大于或等于0(为了防止文本内容太少,导致 cell 高度小于图片高度)

UILabel有四个约束:

左边距离图片8

右边距离contentView右边15

顶部距离contentView顶部8

底部距离contentView底部4

不要忘了将UILabel的numberOfLines设为0

以上约束就可以将contentView撑起来了。

控制器中代码如下:

- (void)viewDidLoad {    [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.tableView.estimatedRowHeight =60;self.tableView.rowHeight =UITableViewAutomaticDimension;    [self.tableView registerNib:[Cell1 nib] forCellReuseIdentifier:[Cell1 identifier]];}

- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {    Cell1 *cell1 = [tableViewdequeueReusableCellWithIdentifier:[Cell1 identifier]forIndexPath:indexPath];    cell1.textLab.text = self.data[indexPath.row];returncell1;}

决定cell自适应内容的也就这两行代码:self.tableView.rowHeight = UITableViewAutomaticDimension; self.tableView.estimatedRowHeight = 60;

看一下效果:

屏幕快照 2016-02-24 上午10.49.42.png

iOS7的自适应cell

iOS7相比iOS8实现起来代码多一点但是并不复杂,还是用上个例子中的cell,

我们在heightForRowAtIndexPath中计算高度:

- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {NSString*identifier = [Cell1 identifier];    Cell1 *cell1 =self.offScreenCells[identifier];if(!cell1) {        cell1 = [[[NSBundlemainBundle] loadNibNamed:@"Cell1"owner:niloptions:nil] lastObject];self.offScreenCells[identifier] = cell1;    }    cell1.textLab.text =self.data[indexPath.row];    [cell1 setNeedsUpdateConstraints];    [cell1 updateConstraintsIfNeeded];CGFloatheight = [cell1.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;returnheight +1;}

这里主要使用systemLayoutSizeFittingSize:来获取内容的高度,所以在获取高度之前我们必须有一个实例化的cell。我在这里使用字典存储cell,主要是因为一个tableView中可能有多种不同的cell。获取到cell之后将内容添加上去,然后更新约束。

屏幕快照 2016-02-24 上午11.27.10.png

要想实现上图效果还有一个需要注意的地方,那就是要给显示label的preferredMaxLayoutWidth赋一个值:

- (void)awakeFromNib {// Initialization codeself.textLab.preferredMaxLayoutWidth =250;}

也可以在给label设置约束时直接将width定死,而不是通过距离contentView右边间距来确定宽度。

以上就是在iOS7及以上版本中实现自适应cell的方法,如果有什么错误,希望大家能指正。你们的支持将是我写作的最大动力。

贴一下demo地址:iOS7和iOS8下的自适应cell

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容