虽然早就知道如何在UITableView中自适应cell的高度,但接手公司项目比较老旧,一直都是手动计算cell高度的,所以也只能写个demo验证一下,还没有在项目中实战。直到前几天有个复杂页面崩溃的问题,我一狠心花了几天时间重构了一下。现记录一下遇到的坑:
手动计算高度
在手动计算cell高度的年代,我们的代码大概是这个样子的
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyModel *model = [self.modelList objectAtIndex:indexPath.row];
return [MyCell heightForModel:model];
}
这样计算出来的高度再做缓存,下次直接取出即可。如果是固定高度也可以写成这样
self.tableView.rowHeight = 44;
但这样的问题就是计算起来太麻烦
使用autolayout计算cell高度
使用autolayout计算cell高度的思路很简单
1、估算cell高度
2、使用autolayout填充cell,保证cell的contentView上下被子视图撑开
self.tableView.estimatedRowHeight = 55;
self.tableView.rowHeight = UITableViewAutomaticDimension;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identify" forIndexPath:indexPath];
[cell.contentView addSubview:self.tipLabel];
//设置top和bottom的margin,再加上label自适应的高度就可以计算出contentview的高度了
[self.tipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(15);
make.right.mas_lessThanOrEqualTo(-15);
make.top.mas_equalTo(15); //设置顶部margin为15
make.bottom.mas_equalTo(-15); //设置底部margin为15
}];
}
如果cell高度是可变的,可以通过以下代理方法来设置cell的估算高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
return 44;
}
else {
return 88;
}
}
使用autolayout计算section header、footer高度
使用autolayout计算section header、footer高度的思路与计算cell高度类似
1、估算header、footer的高度
2、使用子视图撑开header、footer
self.tableView.estimatedSectionHeaderHeight = 10.0;
self.tableView.estimatedSectionFooterHeight = 1.1;
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"identifier"];
[headerView.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
make.height.mas_equalTo(10.0);
}];
return headerView;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UITableViewHeaderFooterView *footerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"identifier"];
[footerView.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
make.height.mas_equalTo(10.0);
}];
return footerView;
}
如果section的header、footer的高度是可变的,可以通过实现以下代理方法来设置section的header、footer估算高度
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section
{
if (section == 0) {
return 10;
}
else {
return 20;
}
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return 10;
}
else {
return 20;
}
}
使用autolayout计算tableHeaderView、tableFooterView的高度
tableHeaderView、tableFooterView还没完全支持autolayout,如果使用autolayout对tableHeaderView、tableFooterView进行布局还需要手动计算frame😓
遇到的坑
1、使用估算高度的时候,与实际高度不能相差太大。否则tableView会闪烁蹦跳
2、估算高度必须大于1,否则在iOS10及以下版本会崩溃
3、UIImageView的高度需要手动制定,否则图片太大的时候不会压缩UIImageView的高度
网友评论