原理:TableView繼承自UIScrollView。所以先要求要有contentView的尺寸,然后具體顯示某個cell的時候再計算cell的高度。所以每次cell顯示的時候都要重新計算他的高度。
二種方案:
一:計算具體cell真實高度。
原理:若有row height或者- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;通過他們直接計算出TableView的contentView高度。當(dāng)顯示某個cell的時候直接調(diào)用他們顯示。優(yōu)先級最高。
方法可以才用手動計算cell的高度,緩存cell的高度避免每次計算。每次顯示的時候先看緩存里面有cell的高度沒有,沒有就計算,計算了放入緩存。cell的高度最好放入Model模型。
二:采用預(yù)估高度,采用約束計算cell真實高度。
原理:若無row height或者- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;通過estimatedRowHeight或者- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);計算出估算的contentView的高度。iOS8之后tableView的row height默認設(shè)置為UITableViewAutomaticDimension, 這個時候具體的某個cell的高度由cell的布局自動計算高度。
預(yù)估高度越接近真實高度越好,若差別過大會出現(xiàn)tableView閃爍跳躍。若cell的高度變化范圍過大且不確定,可用代理設(shè)置預(yù)估高度。第一次將要顯示的時候
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
NSInteger height = cell.height;
[self.cellHeightDic setObject:@(height) forKey:indexPath];
}
可以得到真實高度,然后把高度放入緩存預(yù)估高度數(shù)組。取預(yù)估高度的時候先看有沒有緩存高度有就用緩存高度,沒有就用平均高度。這里由于后面滑動的時候數(shù)組里面都已經(jīng)有了預(yù)估高度且預(yù)估高度就是真實高度,所以完成不會出現(xiàn)閃爍跳躍現(xiàn)象且真實高度就是預(yù)估高度,所以從 預(yù)估—>真實 這一過程就可以忽略影響,達到類似高度緩存的效果。
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSNumber *height = [self.cellHeightDic objectForKey:indexPath];
if(height)
{
return height.floatValue;
}
else
{
return 100;
}
}
cell的布局要求:cell的contentView的子視圖支持起contentView,即每個子視圖上下左右都要有約束,且可以把高度累加,若有大小不固定的圖片最好把圖片的尺寸放入到url里面。若有webView,有待學(xué)習(xí)。
當(dāng)滑動到某個cell的時候每次都要計算cell的高度,這比較費時間可以采第三方UITableView+FDTemplateLayoutCell緩存cell的高度。注意cell中的label先設(shè)定換行寬度,否則要奔潰在高度緩存。 這個第三方好像在iOS10效果不明顯,且有卡頓現(xiàn)象樣,所以除非系統(tǒng)非??D才嘗試用該第三方。
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
self.userName.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 66;
self.descLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [tableView fd_heightForCellWithIdentifier:identify cacheByIndexPath:indexPath configuration:^(MKJTableViewCell *cell)
{
[self configCell:cell indexpath:indexPath];
}];
}
- 若只有某些cell需要計算高度,某些高度固定死了。采用:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 3) {
return 20;//固定死
}else{
return UITableViewAutomaticDimension;//采用約束計算的。
}
}