iOS中tableview是一個(gè)經(jīng)常用的控件,尤其它的cell高度計(jì)算令人頭疼。考慮到tableview的性能優(yōu)化,我們一般都會在model封裝時(shí)提前計(jì)算好cell的高度,代理返回cell高度時(shí),拿到model,直接給它已計(jì)算好的高度。iOS8.0之后,可以使用AutoLayout結(jié)合tableview的屬性讓cell自己計(jì)算出高度。
使用步驟
- cell中使用Autolayout布局,例如這樣:
Cell的AutoLayout樣式.png
cell高度=約束1的值+label1的高度+約束2的值+label2的高度+約束3的值
文字內(nèi)容動態(tài)變化,那么label高度會動態(tài)變化,最終cell高度也會動態(tài)變化。 - 顯設(shè)置tableview的屬性:
//給tableview設(shè)置一個(gè)默認(rèn)高度
self.tableView.estimatedRowHeight = 45;
//告訴tableview,cell是自適應(yīng)的
self.tableView.rowHeight = UITableViewAutomaticDimension;
常遇問題
-
label的lines設(shè)置為1,label不能換行,高度始終是一行的高度,應(yīng)該酌情設(shè)置,一般設(shè)置0即可,不限行高。
image.png -
contentview的高度沒有被子視圖約束填充滿。
image.png -
label的寬度因?yàn)槿鄙偌s束而沒法確定。
image.png -
約束報(bào)錯(cuò),列如:
cell的約束錯(cuò)誤.png
因?yàn)閎ottom的約束值與實(shí)際的值不符,可以改變約束值,或者改變cell的高度
-
使用storyboard繪制的cell,Controller中注冊了cell子類,導(dǎo)致繪制的cell顯示不出來。
cell樣式.png
不需這樣
// [self.tableView registerClass:NSClassFromString(@"MyTableViewCell1") forCellReuseIdentifier:cellId1];
// [self.tableView registerClass:NSClassFromString(@"MyTableViewCell2") forCellReuseIdentifier:cellId2];
直接這樣即可
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row<self.data1.count) {
MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
cell.model=self.data1[indexPath.row];
return cell;
}else
{
MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
cell.model=self.data2[indexPath.row-self.data1.count];
return cell;
}
}
- cell的高度顯示不正確,需要刷新下tableview,才會顯示正確。那是因?yàn)閏ell中l(wèi)abel的賦值是在layoutSubviews完成的。
-(void)layoutSubviews
{
[super layoutSubviews];
self.lbl.text=self.model.contentStr;
}
要么:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row<self.data1.count) {
MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
MyModel1 *model=self.data1[indexPath.row];
cell.lbl1.text=model.str1;
cell.lbl2.text=model.str2;
// cell.model=self.data1[indexPath.row];
return cell;
}else
{
MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
MyModel2 *model=self.data2[indexPath.row];
cell.lbl.text=model.contentStr;
// cell.model=self.data2[indexPath.row-self.data1.count];
return cell;
}
}
很多情況下我們還是希望賦值操作是在cell類中完成時(shí),也可以這樣:
- (void)showData
{
self.lbl1.text=self.model.str1;
self.lbl2.text=self.model.str2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row<self.data1.count) {
MyTableViewCell1 *cell = [tableView dequeueReusableCellWithIdentifier:cellId1 forIndexPath:indexPath];
cell.model=self.data1[indexPath.row];
[cell showData];
return cell;
}else
{
MyTableViewCell2 *cell = [tableView dequeueReusableCellWithIdentifier:cellId2 forIndexPath:indexPath];
cell.model=self.data2[indexPath.row-self.data1.count];
[cell showData];
return cell;
}
}
進(jìn)階
假若label在contentview的多級子視圖中也是可以實(shí)現(xiàn)cell高度自適應(yīng)的。

image.png
原理也是同樣的
demo效果

image.png

image.png
demo在這里





