使用Autolayout實(shí)現(xiàn)cell自適應(yīng)高度

-------推薦使用最下方的【改進(jìn)】方法-------
(前排補(bǔ)上一個(gè)簡(jiǎn)單的小Demo:https://github.com/3KK3/AutoFitDemo/tree/master
時(shí)間倉(cāng)促,有些許不足,敬請(qǐng)見(jiàn)諒。)

方法一:

  1. 對(duì)cell的subview增加針對(duì)于contentView的約束(注意設(shè)置文字的最大寬度);

  2. 設(shè)置tableview預(yù)估高度estimateHeight

  3. 在cell拿到數(shù)據(jù)的地方cellForRowAtIndexPath,進(jìn)行強(qiáng)制刷新布局:先根據(jù)數(shù)據(jù)和cell控件要求計(jì)算實(shí)際高度,并存入dataModel模型(做緩存),然后調(diào)用方法[self layoutIfNeeded](第一次顯示內(nèi)容的時(shí)候 無(wú)需調(diào)用setNeedsLayout),這樣heightForIndexPath會(huì)緊隨其后獲取cell的真實(shí)高度,此時(shí)存入模型的cell的高度就起了作用了

PS:

預(yù)估高度機(jī)制 啟用后 改變cell的加載順序

  • 原來(lái)的順序 : 先調(diào)用heightForRowAtIndexPath獲取真實(shí)高度,拿到高度之后再調(diào)用cellForRowAtIndexPath渲染cell內(nèi)容

  • 啟用預(yù)估高度之后:先調(diào)用estimatedHeightForRowAtIndexPath返回代理估計(jì)高度,然后再根據(jù)預(yù)估高度調(diào)用cellForRowAtIndexPath渲染cell內(nèi)容,同時(shí)計(jì)算真實(shí)高度,最后再調(diào)用heightForRowAtIndexPath拿到計(jì)算的真實(shí)高度 顯示


方法二:

  1. 對(duì)cell的subview增加針對(duì)于contentView的約束(注意設(shè)置文字的最大寬度)

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

       //只創(chuàng)建一個(gè)cell用作測(cè)量高度

  static MyCell *cell = nil;

  if (!cell) cell = [self.tableView  dequeueReusableCellWithIdentifier:@"MyCell"];

     //這里把數(shù)據(jù)設(shè)置給Cell

  cell.titleLabel.text = [_dataSource objectAtIndex:indexPath.row];

  [cell layoutIfNeeded];

  [cell updateConstraintsIfNeeded];



CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

return height;

}


方法三:

1.在cell中設(shè)置多行l(wèi)abel的約束:

// 計(jì)算UILabel的preferredMaxLayoutWidth值,多行時(shí)必須設(shè)置這個(gè)值,否則系統(tǒng)無(wú)法決定Label的寬度
CGFloat preferredMaxWidth = [UIScreen mainScreen].bounds.size.width - (16 + 4) * 2 - 44 - 4;
// Content - 多行
_contentLabel = [UILabel new];
_contentLabel.numberOfLines = 0;
_contentLabel.preferredMaxLayoutWidth = preferredMaxWidth; // 多行時(shí)必須設(shè)置
[self.contentView addSubview:_contentLabel];
[_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {   

    make.top.equalTo(_titleLabel.mas_bottom).with.offset(4);    
    make.left.equalTo(_avatarImageView.mas_right).with.offset(4);   
    make.right.equalTo(self.contentView).with.offset(-4); 
    make.bottom.equalTo(self.contentView).with.offset(-4);}
];
  // 設(shè)置高度的Content Hugging
  [_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

2.UITableView
再看看UITableView。
用systemLayoutSizeFittingSize:獲取Cell的高度
在設(shè)定好Cell的約束以后,就可以用systemLayoutSizeFittingSize:方法獲取Cell的實(shí)際高度,它的參數(shù)可以設(shè)定為兩個(gè)系統(tǒng)常量,如下:
UILayoutFittingCompressedSize: 返回合適的最小大小。
UILayoutFittingExpandedSize: 返回合適的最大大小。

為了在“- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath ”方法中計(jì)算Cell的高度,我們需要一個(gè)專(zhuān)門(mén)用于計(jì)算高度的Cell實(shí)例,可以說(shuō)算是Cell的“模板”。一般來(lái)說(shuō),這個(gè)實(shí)例可以設(shè)置成函數(shù)的static變量,并只在第一次使用時(shí)初始化一次。

model簡(jiǎn)單緩存高度
為了避免每次滑動(dòng)時(shí)計(jì)算高度,可以將Cell的高度緩存下來(lái)。如,保存在每一行對(duì)應(yīng)的數(shù)據(jù)Model(Entity)中,例如:

@interface Entity : NSObject
// Data
@property (copy, nonatomic) NSString *title;
// ...// Cache height
@property (assign, nonatomic) CGFloat cellHeight;
@end

tableView代理方法中代碼:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
 static Case4Cell *templateCell; static dispatch_once_t onceToken; 
dispatch_once(&onceToken, ^{ templateCell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([Case4Cell class])]; });
 // 獲取對(duì)應(yīng)的數(shù)據(jù)
 Case4DataEntity *dataEntity = _data[(NSUInteger) indexPath.row];
 // 填充數(shù)據(jù) 
[templateCell setupData:dataEntity];
 // 判斷高度是否已經(jīng)計(jì)算過(guò)
 if (dataEntity.cellHeight <= 0) { 
  // 根據(jù)當(dāng)前數(shù)據(jù),計(jì)算Cell的高度,
  // ------ 注意+1 ------
  dataEntity.cellHeight = [templateCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1; 
}
 return dataEntity.cellHeight;
}

改進(jìn):

iOS 8的新特性
iOS 8大大簡(jiǎn)化了Cell的高度計(jì)算,只要:
1.設(shè)置好Cell中控件的約束;

  1. 然后 UITabelView初始化時(shí)候:
// UITabelView初始化時(shí)候
tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 80;

3.在UITableview 代理方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
  // 只用返回這個(gè)! 
  return UITableViewAutomaticDimension;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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