1苛骨、屬性介紹
在 iOS7.0之后出現(xiàn)了estimatedRowHeight這個(gè)屬性,
@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
當(dāng)我們?cè)赾ell里面添加完所需控件习蓬,并約束好位置之后,我們只需要設(shè)置
// self-sizing技術(shù) (iOS8 開(kāi)始支持的),iOS8之后默認(rèn)就是這個(gè)值,可以省略
// 告訴tableView所有cell的真實(shí)高度是自動(dòng)計(jì)算的(根據(jù)設(shè)置的約束自動(dòng)計(jì)算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告訴tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;
就可以由系統(tǒng)自動(dòng)計(jì)算高度。
那怎么樣才算約束好呢珍特?才能保證系統(tǒng)準(zhǔn)確的計(jì)算出我們想要的高度呢?
2魔吐、子view布局要求
cell的布局核心:
cell的contentView的子視圖支持起contentView扎筒,即每個(gè)子視圖上下左右都要有約束,最后一個(gè)視圖的bottom要設(shè)置的和contentView的bottom一樣酬姆。這樣寬高都有了嗜桌,就可以自動(dòng)進(jìn)行約束了
[self.contentView addSubview:_contentLabel];
[self.contentView addSubview:_headerImage];
// 約束可以直接放在創(chuàng)建的地方
// 不要放在layoutSubviews 或 updateConstraints方法里
[_headerImage mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(10);
make.top.equalTo(self.contentView).offset(20);
make.height.width.equalTo(@50);
}];
[_contentLabel mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(_headerImage.mas_bottom).offset(5);
make.left.right.equalTo(self.contentView);
// 這一步是關(guān)鍵 讓cell知道最底部在哪兒, 然后算出自身高度
make.bottom.equalTo(self.contentView);
}];
參考布局博文:
UITableViewCell高度自適應(yīng) 使用Masonry純代碼約束
3、進(jìn)一步理解自動(dòng)計(jì)算高度
我想在大家初次解決tableViewCell高度自適應(yīng)問(wèn)題的時(shí)候應(yīng)該會(huì)這樣想過(guò):在繪制cell的時(shí)候我們可以得到cell準(zhǔn)確的高度,如果拿到這個(gè)高度設(shè)置成cell的高度不是剛剛好嗎? 悲劇的是tableView顯示數(shù)據(jù)的時(shí)候會(huì)先調(diào)用高度的協(xié)議方法(heightForRow...),然后才進(jìn)行繪制(調(diào)用cellForRow...),也就是說(shuō),調(diào)用高度的時(shí)候cell可能都還不存在呢!
tableView: estimatedHeightForRowAtIndexPath:就是為了改變這個(gè)問(wèn)題誕生的.我們用數(shù)據(jù)說(shuō)話:當(dāng)我們沒(méi)有調(diào)用estimatedHeightForRow...這個(gè)方法的時(shí)候,tableView調(diào)用幾個(gè)代理方法的順序是這樣的:(測(cè)試數(shù)據(jù)為5行)
可以看出,控制器在得知cell的行數(shù)n之后,會(huì)先一口氣調(diào)用n次heightForRow方法,這是為了方便tableView計(jì)算自己的contentSize,進(jìn)一步計(jì)算指示條的大小和位置.
在添加了estimatedHeightForRow...方法后,調(diào)用順序變成了:
也就是說(shuō),愿望實(shí)現(xiàn)了. 這個(gè)方法的出現(xiàn)使得tableView代理方法的調(diào)用順序發(fā)生了改變,從而達(dá)到了前面說(shuō)的"繪制cell時(shí)得到準(zhǔn)確高度,然后把高度再拿給tableView去顯示"的目的.并且,這個(gè)方法避免了一開(kāi)始調(diào)用n次heightForRow的方法導(dǎo)致的一些不必要的計(jì)算.
4轴踱、關(guān)于性能方面
可以參考博文[5]
其實(shí)在官方文檔中已經(jīng)有詳細(xì)的介紹:
利用預(yù)估的高度症脂,可以提升tableView的加載數(shù)據(jù)的性能。
那如果我們想要一部分cell需要手動(dòng)計(jì)算高度淫僻,而另一部分cell需要自動(dòng)計(jì)算高度诱篷,又該如何處理呢?
其實(shí)雳灵,關(guān)鍵在于以下核心代碼:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 || indexPath.section == 1) {
return 81;
}
// 注意:解決固定行高和系統(tǒng)自動(dòng)計(jì)算行高 其他組走系統(tǒng)自動(dòng)計(jì)算行高
return UITableViewAutomaticDimension;
}
想用預(yù)估帕翻,直接返回UITableViewAutomaticDimension,否則返回計(jì)算的高度哄陶。追根溯源我們參考文檔描述,如下: