UITableView自动(手动)混合计算高度

2020-02-17  本文已影响0人  perfect_coding

1、属性介绍

在 iOS7.0之后出现了estimatedRowHeight这个属性,
@property (nonatomic) CGFloat estimatedRowHeight NS_AVAILABLE_IOS(7_0); // default is UITableViewAutomaticDimension, set to 0 to disable
当我们在cell里面添加完所需控件,并约束好位置之后,我们只需要设置

// self-sizing技术 (iOS8 开始支持的),iOS8之后默认就是这个值,可以省略
// 告诉tableView所有cell的真实高度是自动计算的(根据设置的约束自动计算)
self.tableView.rowHeight = UITableViewAutomaticDimension;
// 告诉tableView所有cell的估算高度
self.tableView.estimatedRowHeight = 44;

就可以由系统自动计算高度。
那怎么样才算约束好呢?才能保证系统准确的计算出我们想要的高度呢?

2、子view布局要求

cell的布局核心:
cell的contentView的子视图支持起contentView,即每个子视图上下左右都要有约束,最后一个视图的bottom要设置的和contentView的bottom一样。这样宽高都有了,就可以自动进行约束了

     [self.contentView addSubview:_contentLabel];
     [self.contentView addSubview:_headerImage];
        // 约束可以直接放在创建的地方
        // 不要放在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);
            // 这一步是关键 让cell知道最底部在哪儿, 然后算出自身高度
            make.bottom.equalTo(self.contentView);
        }];

参考布局博文
UITableViewCell高度自适应 使用Masonry纯代码约束

3、进一步理解自动计算高度

我想在大家初次解决tableViewCell高度自适应问题的时候应该会这样想过:在绘制cell的时候我们可以得到cell准确的高度,如果拿到这个高度设置成cell的高度不是刚刚好吗? 悲剧的是tableView显示数据的时候会先调用高度的协议方法(heightForRow...),然后才进行绘制(调用cellForRow...),也就是说,调用高度的时候cell可能都还不存在呢!

tableView: estimatedHeightForRowAtIndexPath:就是为了改变这个问题诞生的.我们用数据说话:当我们没有调用estimatedHeightForRow...这个方法的时候,tableView调用几个代理方法的顺序是这样的:(测试数据为5行)

image.png

可以看出,控制器在得知cell的行数n之后,会先一口气调用n次heightForRow方法,这是为了方便tableView计算自己的contentSize,进一步计算指示条的大小和位置.

在添加了estimatedHeightForRow...方法后,调用顺序变成了:

image

也就是说,愿望实现了. 这个方法的出现使得tableView代理方法的调用顺序发生了改变,从而达到了前面说的"绘制cell时得到准确高度,然后把高度再拿给tableView去显示"的目的.并且,这个方法避免了一开始调用n次heightForRow的方法导致的一些不必要的计算.

4、关于性能方面

可以参考博文[5]
其实在官方文档中已经有详细的介绍:


image.png

利用预估的高度,可以提升tableView的加载数据的性能。

那如果我们想要一部分cell需要手动计算高度,而另一部分cell需要自动计算高度,又该如何处理呢?

其实,关键在于以下核心代码:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0 || indexPath.section == 1) {
            return 81;
    }
    // 注意:解决固定行高和系统自动计算行高  其他组走系统自动计算行高
    return UITableViewAutomaticDimension;
}

想用预估,直接返回UITableViewAutomaticDimension,否则返回计算的高度。追根溯源我们参考文档描述,如下:


image.png

参考博文:

  1. UITableViewCell高度自适应探索
  2. iOS UITableView 解决估算行高和指定行高的矛盾
  3. UITableView自动计算Cell高度思路
  4. UITableView高度问题
  5. iOS开发中行高灵活可变的UITableView的性能优化
上一篇下一篇

猜你喜欢

热点阅读