iOS 端使用嵌套 UIScrollView 实现类似淘宝首页效果

本文最后更新于 2021年4月4日 晚上

现在许多 APP 都有这样的需求, 就是在底层的滑动视图(UIScrollView)上再内嵌一个集合视图(UICollectionView)或表格视图(UITableView), 即常说的 “Scroll view inside scroll view”. 正好在公司的需求中遇到了, 记录下整个实现过程.

传统做法

传统做法主要有如下:

  • 滑动联动切换: 在滑动超过内部集合视图顶部后由滑动视图接管处理滚动手势, 这样的手势处理十分繁琐复杂, 要考虑的内容很多.

  • 修改内部滚动视图高度等于内容视图(content view)的高度: 这个方法是最笨的, 如果对于少量数据来说, 却可以使用这样的办法, 因为实现简单… 但缺点也很明显, 一旦在开始就把滚动视图的高度设置为内容视图高度后, 重用算法就成了摆设…

  • 通过修改 contentInset 值, 在滑动视图上方(或下方)开辟 “内容区域”. 这个在做法上可行, 也比较简单, 且性能上也没有额外负担. 但缺点是无法满足一些需求场景.

参考:

  1. 这个是一个仿淘宝的工程, 有启发价值.

  2. 解除嵌套滑动视图之间的联动.

一种高效的滑动栈视图实现方法

参考如下:

  1. 高效滑动栈视图实现.

  2. 滑动视图的嵌套.

  3. WWDC2013 Session 217

通过上述参考文章, 发现了一种实现简单, 性能优异的解决方案. 主要思路就是在父滑动视图滑动时, 动态修改某个子滑动视图的 frame(“窗户”在父滑动内容视图上的位置和大小), 以及子滑动视图相对应的 contentOffset 值(“窗户”里面”风景”的位置), 以获得和滑动该子视图时同样的效果, 且苹果提供的重用算法不受任何影响.

而这种方法的实现代码在参考 1 文章中已经有了, 经实测可以支持 Self-Sizing, 下拉加载更多等各类需求, 因为本身并没有修改滑动视图的任何内部实现细节.

具体效果可以看下面这个图, 图中上方是一个固定高度的 View, 而下方是一个 TableView(其中 border 是通过 chisel 添加的):


iOS 端使用嵌套 UIScrollView 实现类似淘宝首页效果
https://blog.rayy.top/2018/10/04/2019-9-UICollectionViewInsideUIScrollView/
作者
貘鸣
发布于
2018年10月4日
许可协议