索鸟网

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

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代码和效果如下:

如果把layoutSubviews中的布局约束写在 initWihStyle函数中 addSubviews之后就是正常:

另外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的高度,让系统计算别的控件的布局高度:

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


  • 总结

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

  • 感谢

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

objective-c

来源地址:https://segmentfault.com/a/1190000010465823 版权归作者所有!

相关教程

  • 聊天界面-自适应文字

    该篇文章主要介绍一个实现聊天界面的思路过程,源码可以在 源码链接 获得,该工程实现聊天的基本功能,功能还不够完善,欢迎大家提 PR ,效果图如下所示 我希望通过相对简单的方式实现界面的布局,没有复杂的计算达到自适应的效果。 iOS8 新功能介绍 虽然 self size cell 最终没有在我的工程中用到,但是这是我曾经挖过的坑,所以在此做了简单的介
  • iOS11问题汇总

    iOS11最终还是来了, 这次改版屏幕尺寸, 控件特性都有一些比较大的改变. 网上看的问题零零散散, ?收集了一下开发中出现的问题, 整理一下, 方便之后使用. 1. 导航栏 导航栏高度一直是固定的64P, 到了iOS11这个规则被打破了, 除了iPhoneX全面屏, 刘海等适配问题, 还增加了大标题的属性, titleView支持autolayout
  • Masonry和FDTemplateLayoutCell搭配使用「UITableview自适应内容高度」

    一、准备 1.FDTemplateLayoutCell 由sunny大神出品的自动计算UITableviewCell高度FDTemplateLayoutCell_下载 2.Masonry 目前最流行的AutoLayout框架,比较轻量级Masonry_下载 将上述两个第三方下载后(或者使用Cocoapods)导入工程,然后创建所需文件,此时的工程目录
  • 弹性盒模型Flex指南

    原文: 弹性盒模型Flex指南 Web layout 是Web UI中的基础架构, 重要性不言而喻. 传统的盒模型, 借助display, position, float 属性应对普通布局游刃有余, 但针对复杂的或自适应布局, 常常捉襟见肘. 比如垂直居中, 就是一个老大难的问题, 借助flex弹性盒模型, 两行代码就可以优雅的实现之. (该方法曾在 1
  • Agora iOS SDK-多人聊天

    在上一篇Agora iOS SDK-开始聊天介绍了如何使用Agora SDK进行一对一的聊天,这篇主要介绍下如何使用Agora iOS进行多人聊天,需要实现的功能: 随着加入人数的变化,而显示不同的UI,主要是分屏 在多屏显示的情况下,点击一个小窗,会放大显示该聊天窗 前篇实现的聊天功能 实现上面所说的功能:分屏,最好的方式是使用瀑布流布局,这样可以
  • [干货系列--分量充足]Android开发的那些坑和小技巧

    1、android:clipToPadding 意思是控件的绘制区域是否在padding里面。默认为true。如果你设置了此属性值为false,就能实现一个在布局上事半功陪的效果。先看一个效果图。 上图中的ListView顶部默认有一个间距,向上滑动后,间距消失,如下图所示。 如果使用margin或padding,都不能实现这个效果。加一个headerView又显得
  • 这可能是史上最全的CSS自适应布局总结

    所谓布局,其实包含两个含义:尺寸与定位。也就是说,所有与尺寸和定位相关的属性,都可以用来布局。 大体上,布局中会用到的有:尺寸相关的盒子模型,普通流、浮动、绝对定位三种定位机制,CSS3中的transform、弹性盒子模块、试验中的grid模块。逛园子的时候经常可以看到浮动布局,inline-block布局,弹性盒布局这几个名词。现在对布局也算有一点了解,做个总结巩固一
  • css布局,左右固定中间自适应实现

    1.绝对定位+浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>布局测试</title> </head> <style type="text/css">