TableViewCell高度自适应

相信很多朋友都深有体会,tableViewCell的高度计算的总是不尽人意

很多时候我们在项目中的cell会是多种多样的,当cell中含有高度不固定的文本labeltextView时怎么办

这里先列举几个之前的例子:

示例 : One

小白一点的朋友们会发现当我们在cell中进行高度计算然后return高度,再在控制器中调用是不可取的,原因在于tableView的代理方法heightForRowAtIndexPath会在cellForRowAtIndexPath之前调用
这个时候cell还未创建,可能会导致程序的crash, 调用类似于下面这种形式:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    BaseModelCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    
    return [cell cellHeight];

}

示例 : Two

cell中不行,我们就在model里赋值好了,很多时候我们的高度计算会在model中长这个样子:

-(CGFloat)cellHeight{
    
    UIFont *currentFont = [ThreePicModel currentFont];
    
    CGRect labelrect = [self.title boundingRectWithSize:Size(WidthScale_IOS6(316), MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin |
                        NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName:currentFont} context:nil];
    if (iPhone5 || iPhone4) {
        return labelrect.size.height+HeightScale_IOS6(170);
    }else{
        
        //计算出自适应的高度
        return labelrect.size.height+HeightScale_IOS6(155);
    }
}

然后在控制器中调用:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    BaseModel *model = self.dataModelAry[indexPath.section];
    return model.cellHeight;
}

当然,这种方法是可行的,只要判断做的足够多,我们的cell呈现出来也是可以接受的,但是很多coder门已经厌倦了boundingRectWithSize这个方法了,工作了的朋友估计也会遇到iOS8系统下boundingRectWithSize这个方法有时会导致crash

示例 : Three

我们还可以判断版本用创建方法计算,类似这个样子:

    UILabel *textLabel = [[UILabel alloc]init];
    textLabel.font = [UIFont systemFontOfSize:14];
    textLabel.text = [self.user_id stringByAppendingString:[NSString stringWithFormat:@":%@",self.comment]];
    textLabel.numberOfLines = 0;//根据最大行数需求来设置
    textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
    CGSize maximumLabelSize = CGSizeMake(Screen_width - 88, MAXFLOAT);//labelsize的最大值
    CGSize finalSize = [textLabel sizeThatFits:maximumLabelSize];
    return finalSize.height;

coder们别喷我,我当年用过这个办法进行高度计算,而且我验证过,此方法计算出的高度比boundingRectWithSize计算出来的高度更贴切

好啦~我知道致命的问题,这种方法,循环创建,什么工程也不会允许这么愚蠢的方法...

示例 : Four

那么还有什么方法呢?在github上我发现了这样一个库(喜欢钻研的人士可以传送门去瞧瞧):

一看简介着实吓了我一条 7000+star简直要媲美我大MJ了,当然网上有说利用这个库实现高度自适应是最屌的,我也觉得很厉害,下面开启传送门(ps一下有玩炉石的coder们么),在工程中使用大体是这个样子的:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) {

      // 配置 cell 的数据源,和 "cellForRow" 干的事一致,比如:
     cell.entity=self.feedEntities[indexPath.row];

}];
}

RunLoop 解决iOS 7以下高度问题,这个库统统包含,可是我本人总是觉得工程中尽量少用第三方库,至少我们产品经理总是这样教育我们,那么还有什么方法呢?

示例 : Five

Masonry + 适配宏也很爽,配合labelsizeToFit瞬间轻松了,但是会发现cell一般我们都是会用xib进行创建,很少纯代码,至少我是这样,那还有没有更爽的方法了

    [self.summaryLabel sizeToFit];
    
    [self.summaryLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(Size(WidthScale_IOS6(28),HeightScale_IOS6(20)));
        make.left.offset(space);
        make.centerY.equalTo(self.mas_centerY);
    }];

示例 : Six

看好了,如果你的项目适配的最低版本是iOS 8.0,那么接下来的两行代码将改变所有对于高度的计算:

    self.tableView.estimatedRowHeight = 150;//估算高度
    self.tableView.rowHeight = UITableViewAutomaticDimension;
    

tableViewestimatedRowHeight 这个特性是在iOS 7以后才存在,貌似在iOS 8以后才少了许多7中出现的bug,比如在7中你用这个estimatedRowHeight会导致滚动条的大小处于不稳定的状态,contentSize会随着滚动从估算高度慢慢替换成真实高度,这完全可以通过肉眼看出 (当然如果你的公司不适配7的话,你懂得😉)

我们看一下 estimatedRowHeight 官方文档给的解释

The estimated height of rows in the table view.
Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view. If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.
When you create a self-sizing table view cell, you need to set this property and use constraints to define the cell’s size.
The default value is 0, which means there is no estimate.

大体意思是针对iOS 8以后的,接下来是渣渣翻译:

当你创建一个self-sizing表视图单元格时,你需要设置这个属性并且使用约束来定义单元格的尺寸。默认值为0,这意味着没有预估高度

OK,文档很清楚的说明了需要配合约束一起使用,那么我们可以试一下在xib中创建一个带Labelcell,label的高度不固定,其他上下左右约束需要约好,将这两行代码加入控制器中:

cell自适应

cell高度已经完美自适应了,值得注意的是,在这两行代码加入后,需要注释掉heightForRowAtIndexPath因为一旦设置heightForRowAtIndexPath将不会遵循tableViewrowHeight

//-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//    
//}

另外如果出现高度还是不对的童鞋们,出现下方这种情况:

示例

请在xib中保证label的上下左右都有约束,不过有时候label虽然有约束但是同label进行约束的对象不固定,例如:

示例2

这个label针对下面View进行了bottom但是View却没有对点击查看有bottom的约束,(好像没有说的很明白)

可以用一个方法检测一下约束,保证xib是一块整体,当我们对cell进行拉伸时:

示例3

就会出现这种警告,其实我们是多加了针对点击查看对上面分割线的约束,虽然这条约束是多余的,但是保证了cell的高度被固定了起来,这样当我们再次运行的时候就会看到我们理想中cell的样子了,当然其实tableViewrowHeight 默认就是UITableViewAutomaticDimension,所以我们只要预估一下高度,并且约束好就可以达到高度的自适应了.

好了,这种方法是我一直在用的,避免了繁琐的高度计算,如果coder们有更好的提议,请评论私信我,觉得有用的请点个赞吧~

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

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,617评论 4 59
  • 我们在上一篇《通过代码自定义不等高cell》中学习了tableView的相关知识,本文将在上文的基础上,利用sto...
    啊世ka阅读 1,435评论 2 7
  • 急报 急报 猛烈台风就到, 阳光浅笑西边 风平浪静好天, 天好 天好 一场虚惊飘渺。
    唐春元ok阅读 465评论 14 24
  • 我是一个看过很多书的孩子,也的确受益于书,但我不认为自己是一个文艺的人,反倒像是一个病患,一个心理有问题的人。
    往生树阅读 174评论 0 0
  • C城一面临海,三面环山。城市大致被分为南北两半,北城聚集了大部分城市的中心和高级地段,终日的灯红酒绿遍布于此...
    阿帆帆阅读 416评论 0 1