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代码和效果以下:
图片描述
图片描述spa

若是把layoutSubviews中的布局约束写在 initWihStyle函数中 addSubviews以后就是正常:
图片描述
图片描述3d

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

  • 机制猜测对象

为何layoutSubView中去进行约束影响了系统去计算高度呢?进行了代码追踪后猜测的结果是estimate是在全部垂直条件都知足的状况下才能计算出高度,不然用预设高度。而且计算高度的时机是要快于layoutSunview方法的触发的,也就是说在layoutSubview去写约束的话会致使约束滞后,系统计算超前。并且用layoutSubViews方法时须要注意时机:每次label进行赋值的时候或者tableView滑动的时候都会触发layoutSubViews方法。blog

  • 系统自动计算内容图片

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

  • 遇坑例子

重点来了,系统自动计算高度在cell中是计算contentView里控件的约束高度好比在headerView或者footerView中用imageView设置背景图的时候,若是全部的控件都是经过self.contentView addSubview的方式进行添加的话,那么背景图imageView不要添加在self.contentView上,由于背景图都是上下左右约束好的或者frame = self.frame。这样就知足了预设定高度的系统计算条件,会拿imageView的高度做为计算计算结果,因此下面动态高度的控件也就不会自适应了。那么就想一个办法,不让系统计算高度去计算imageView的高度,让系统计算别的控件的布局高度:
图片描述

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

图片描述
图片描述

  • 总结

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

  • 感谢

时间比较仓促简单记录一下工做中碰见的问题和本身的一点点看法, 若是有不足之处或者错误理解的地方欢迎各位道友指出谢谢~

相关文章
相关标签/搜索