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閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容

  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,179評論 4 61
  • 我們在上一篇《通過代碼自定義不等高cell》中學習了tableView的相關知識,本文將在上文的基礎上,利用sto...
    啊世ka閱讀 1,526評論 2 7
  • 急報 急報 猛烈臺風就到, 陽光淺笑西邊 風平浪靜好天, 天好 天好 一場虛驚飄渺。
    唐春元ok閱讀 500評論 14 24
  • 我是一個看過很多書的孩子,也的確受益于書,但我不認為自己是一個文藝的人,反倒像是一個病患,一個心理有問題的人。
    往生樹閱讀 192評論 0 0
  • C城一面臨海,三面環山。城市大致被分為南北兩半,北城聚集了大部分城市的中心和高級地段,終日的燈紅酒綠遍布于此...
    阿帆帆閱讀 457評論 0 1