四種方法實現(xiàn)UITableView的cell高度自動計算

UITableview是iOS開發(fā)中使用最頻繁的一個控件,在實際開發(fā)中,我們經(jīng)常需要定制cell,讓cell顯示圖片、文字等。由于cell包含的圖片和文字是根據(jù)服務(wù)器返回的數(shù)據(jù)進行填充的,這就導(dǎo)致cell包含的內(nèi)容的高度是不定的。

四種方法計算cell的高度:

1、iOS8的自動計算機制,需要autolayout(適用iOS8之后系統(tǒng))2、iOS6之后系統(tǒng)API結(jié)合autolayout進行計算(適用于iOS6之后的系統(tǒng))3、手動計算(適用于iOS6之后的系統(tǒng))4、借助于第三方框架自動計算(適用于iOS6之后的系統(tǒng))方法1:iOS8的自動計算
此方法必須使用autolayout,這里我是用的xib設(shè)置的,也可以使用第三方框架masonry設(shè)置。
設(shè)置約束的時候必須注意每個控件在垂直方向上必須都有約束,這樣cell才可以計算出來高度。下面我們來看看cell的內(nèi)部控件的垂直方向的約束如何設(shè)置
昵稱label的垂直約束

內(nèi)容文字label的垂直約束

內(nèi)容圖片的垂直約束
height <= 400這個約束也可以不用設(shè)置,我這里是為了不讓圖片過長,所以限制了高度。


下面我只貼出計算高度的代碼,整個Demo我會放大github上面。

具體實現(xiàn)代碼
iOS8時代的高度計算非常簡單,下面兩行代碼就搞定了,非常方便。前提是需要設(shè)置好在垂直高度上的約束。

- (void)viewDidLoad{      
    self.tableView.estimatedRowHeight = 80.0f;  
    self.tableView.rowHeight = UITableViewAutomaticDimension;  
}  

效果如下


方法2:iOS6的系統(tǒng)API結(jié)合autolayout
控件的約束和第一個方法的一樣,下面列出的代碼是和第一個方法不同的地方。該方法的demo和第一個方法的demo是同一個,每個方法獨立使用到的代碼我會特別注明,沒有注明就是所有方法共有的。

//TableViewCell.m文件  
//======================  
- (void)setModel:(TableViewModel *)model  
{  
    //必須設(shè)置label的最大寬度,不然系統(tǒng)無法計算label的最大高度  
    CGFloat preferredWidth = [UIScreen mainScreen].bounds.size.width - 53;  
    self.userName.preferredMaxLayoutWidth = preferredWidth;  
    self.userContentString.preferredMaxLayoutWidth = preferredWidth;  
  
    self.headImage.image = model.userHeadImage;  
    self.userContentImage.image = model.userContentImage;  
    self.userContentString.text = model.userContentString;  
    self.userName.text = model.userName;  
}  
//viewController.m文件  
//===========================  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  
    static TableViewCell *Cell;  
    static dispatch_once_t onceToken;  
    //必須使用dispatch_once,保證只會從緩存池中取一個cell用于高度計算,其他的cell高度都是用這個cell的高度。不然每次都從緩存池中取出來不同的cell,導(dǎo)致高度計算出問題  
    dispatch_once(&onceToken, ^{  
        Cell = [tableView dequeueReusableCellWithIdentifier:CellId];  
    });  
  
   TableViewModel *model = self.modelArray[indexPath.row];  
    Cell.model = model;  
    // 根據(jù)當(dāng)前數(shù)據(jù),計算Cell的高度,注意+1是contentview和cell之間的分割線高度  
    model.cellHeight = [Cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height +1.0f;  
   return model.cellHeight;  
}  
  
//實現(xiàn)該方法后,tableview就不會一次性調(diào)用完所有cell的高度,有些不在可見范圍的cell是不需要一開始就知道高度的。當(dāng)然,estimatedHeightForRowAtIndexPath方法調(diào)用頻率就會非常高,所以我們盡量返回一個比較接近實際結(jié)果的固定值以提高性能.  
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {  
    return 112.0f;  
}  

該方法實現(xiàn)效果和方法一相同

方法3、手動計算

該方法需要手動計算垂直高度上每個控件的高度,然后相加得出cell的高度。這種方法最繁瑣,但是也是最精確的,也是最可控的。使用這個方法,可以不需要使用autolayout設(shè)置約束,直接使用frame設(shè)置每個控件的位置。但是為了方便,我這里還是使用autolayout設(shè)置控件的約束和位置。
因為需要確切的知道每個控件的高度,所以這里image的高度必須是固定的,這樣才可以進行cell的高度計算修改如下


修改的代碼如下:

//TableViewModel.m文件  
//===============================  
#import "TableViewModel.h"  
  
@implementation TableViewModel  
  
//方法3代碼  
- (CGFloat)cellHeight{  
    // 文字的最大尺寸(設(shè)置內(nèi)容label的最大size,這樣才可以計算label的實際高度,需要設(shè)置最大寬度,但是最大高度不需要設(shè)置,只需要設(shè)置為最大浮點值即可),53為內(nèi)容label到cell左邊的距離  
    CGSize maxSize = CGSizeMake([UIScreen mainScreen].bounds.size.width - 53, MAXFLOAT);  
  
    // 計算內(nèi)容label的高度  
    CGFloat textH = [self.userContentString boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:14]} context:nil].size.height;  
  
    /* 
     昵稱label和cell的頂部為0 
     17為昵稱label的高度 
     8.5為昵稱label和內(nèi)容label的間距 
     textH為內(nèi)容label的高度 
     304為內(nèi)容image的高度 
     */  
    _cellHeight = 0 + 17 + 8.5 + 8 +textH + 304;  
  
    return _cellHeight;  
}  
//ViewController.m文件  
//==========================  
  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  
 //方法3代碼  
   TableViewModel *model =  self.modelArray[indexPath.row];  
    return model.cellHeight;  
}  

方法四、使用第三方框架

這是國內(nèi)的一個大神寫的框架,可以一行代碼就實現(xiàn)cell的高度自動計算。同時還能實現(xiàn)緩存高度,最低兼容版本為iOS6。實現(xiàn)代碼就不寫了,非常簡單
具體看這篇文章:《優(yōu)化UITableViewCell高度計算的那些事
這里啰嗦兩點,也是自己踩過的坑:
1、在博主的文字里面提到使用的時候直接使用如下代碼即可:

#import <UITableView+FDTemplateLayoutCell.h>  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {  
    return [tableView fd_heightForCellWithIdentifier:@"identifer" cacheByIndexPath:indexPath configuration:^(id cell) {  
        // 配置 cell 的數(shù)據(jù)源,和 "cellForRow" 干的事一致,比如:  
        cell.entity = self.feedEntities[indexPath.row];  
    }];  
}  

一定要把上面的id cell,換成自己的cell類,比如我的就是WSTableViewCell *cell。算是一個小坑吧。
2、很多人肯定吃過self-sizing-cell的虧,覺得我上面都設(shè)置對了,為什么就是算不出來高度呢?
要滿足self-sizing-cell,必須滿足兩點:
你的cell里面的控件必須在上下左右四個方向都有約束到cell的四個邊。如下圖:

*約束一定要是控件和cell的contentView邊緣之間的約束,而不是控件和cell邊緣的之間的約束。
因為設(shè)計給的圖,cell內(nèi)部的控件和cell的距離是到cell邊緣的距離,然后我就發(fā)現(xiàn)怎么都不能進行高度自動計算,所有的cell全部疊在一起了。被這個坑了很久,一直找不出來原因。另外cell的邊緣和cell的contentView的邊緣相差8pt。
錯誤設(shè)置:
ReplayCell是cell的名字


正確設(shè)置:

superView是cell的contentView



總結(jié):

上面四種方法各有優(yōu)缺點,如果你的App最低兼容版本是iOS8,那請毫不猶豫的選擇方法一的系統(tǒng)方法吧,高效簡潔。
如果你需要最低兼容iOS6,可以從其他三個方法中選一個,建議使用方法四的第三方框架,高效強大。
所有的代碼都放在了Github上面,小伙伴們可以參考下。

地址如下:https://github.com/XiMu-Demo/Blog-Demo/tree/master/calculateCellHeight

百度 開源的一個自動計算Cell 高度 第三方UITableView-FDTemplateLayoutCell-master
http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • UITableview是iOS開發(fā)中使用最頻繁的一個控件,在實際開發(fā)中,我們經(jīng)常需要定制cell,讓cell顯示圖...
    西木柚子閱讀 9,405評論 25 97
  • 我們在上一篇《通過代碼自定義不等高cell》中學(xué)習(xí)了tableView的相關(guān)知識,本文將在上文的基礎(chǔ)上,利用sto...
    啊世ka閱讀 1,655評論 2 7
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,408評論 4 61
  • 伴隨著淅淅瀝瀝的秋雨帶來的涼意,好像這個秋天真的來了,這是我與你一起度過的第一個秋天。我們從春天相識,相愛...
    宋花花呀閱讀 562評論 0 0
  • 眾所周知,基礎(chǔ)數(shù)組的處理效率要比集合的處理效率高出指數(shù)倍(內(nèi)存尋址優(yōu)勢,指哪打哪,直截了當(dāng)) 在HashMap<K...
    8c3c932b5ffd閱讀 210評論 0 0

友情鏈接更多精彩內(nèi)容