iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑

iOS estimate预设高度自适应

  • 前提

在iOS开发中tableView的cell自适应高度是常见的需求,之前采取过masonry约束布局cell内部计算最终高度进行高度缓存返回的方式,这样的优点比较高效,但是计算高度代码相对复杂。在没有追求极致计算效率的前提下,昨天尝试了下系统提供的estimate设置预估值高度后系统会根据约束自动计算高度。

  • 问题

首先扯一点同事关于布局约束的使用的问题,自定义cell .m文件中重写initWithStyle方法进行了cell上控件创建和添加。但是约束写在了layoutSubviews方法里。这样在通常情况下是没有问题的,但是昨天我在此代码基础上去用预估值高度进行cell自适应高度时,发现了约束错乱的结果,并且没有高度自动计算。于是写个demo找原因,控制器中预设高度自适应核心代码self.tableView.estimatedRowHeight = 100;self.tableView.rowHeight = UITableViewAutomaticDimension;
自定义cell .m代码和效果如下:
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第1张图片
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第2张图片

如果把layoutSubviews中的布局约束写在 initWihStyle函数中 addSubviews之后就是正常:
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第3张图片
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第4张图片

另外cell自定义xib进行拖线Autolayout约束也是正常的,只要约束是正确的:垂直方向约束从上到下一定要饱满 top bottom 都满足,那么系统去根据约束计算的时候就不会差。否则基本都是约束条件不满足造成的混乱。

  • 机制猜想

为什么layoutSubView中去进行约束影响了系统去计算高度呢?进行了代码追踪后猜想的结果是estimate是在所有垂直条件都满足的情况下才能计算出高度,否则用预设高度。并且计算高度的时机是要快于layoutSunview方法的触发的,也就是说在layoutSubview去写约束的话会导致约束滞后,系统计算超前。而且用layoutSubViews方法时需要注意时机:每次label进行赋值的时候或者tableView滑动的时候都会触发layoutSubViews方法。

  • 系统自动计算内容

另系统提供了estimatedRowHeight(cell高度预估值)、estimatedSectionHeaderHeight(headerView预估值)、estimatedSectionFooterHeight(footerView预估值)三个部位都可以让系统自动计算高度。

  • 遇坑例子

重点来了,系统自动计算高度在cell中是计算contentView里控件的约束高度比如在headerView或者footerView中用imageView设置背景图的时候,如果所有的控件都是通过self.contentView addSubview的方式进行添加的话,那么背景图imageView不要添加在self.contentView上,因为背景图都是上下左右约束好的或者frame = self.frame。这样就满足了预设定高度的系统计算条件,会拿imageView的高度作为计算计算结果,所以下面动态高度的控件也就不会自适应了。那么就想一个办法,不让系统计算高度去计算imageView的高度,让系统计算别的控件的布局高度:
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第5张图片

没错,这么写imageView会覆盖所有控件,所以[self insertSubview:_backGrooundImageView belowSubview:self.contentView];把iamgeView压到了self.contentView下面,这样的话既不会覆盖也不会被系统计算高度。结果就是contentView上面所有的控件高度约束计算出来后,返回这个高度,并且背景图imageView不受影响。

iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第6张图片
iOS 预估值estimatedHeight实现headerView和cell自适应高度布局机制踩坑_第7张图片

  • 总结

1、用头视图来总结:在头视图创建之前,系统用预设高度作为heightForHeader的高度进行绘制,在控件都加载出来之后并且约束确定之后计算出控件约束的真实高度再次返回(heghtForHeader代理方法会走两次)。
2、系统自动计算高度的时机是在cententView内容绘制成功后。准确计算出高度的充分条件是控件垂直方向约束要“完美”。注意有top和bottom的约束是否满足,否则会混乱。
3、系统计算高度的对象是contentView层上的控件。

  • 感谢

时间比较仓促简单记录一下工作中遇见的问题和自己的一点点见解, 如果有不足之处或者错误理解的地方欢迎各位道友指出谢谢~

你可能感兴趣的:(objective-c)