grouped UITableView行动画时分组间隙透明致动画重叠如何解决
grouped UITableView 分区展开收起动画穿透问题解决
问题本质
grouped 样式的 UITableView 自带的分区间隙是没有实体视图的空白区域,根本没有可承载遮挡能力的UI元素。执行行插入、删除的动画时,系统会生成临时的cell动画快照层,这层快照在间隙位置没有任何东西挡着,就会直接穿过去和其他分区的内容叠在一起。自定义分区头是有实体视图的,而且层级比动画快照高,能挡住自身覆盖范围的动画,所以才会出现只有第一个分区动画正常,其他分区一执行动画就跨区重叠的情况。
在间隙上叠加不透明视图的思路完全可行,按照下面的优先级选实现方式就行:
- 最省事的方案:给tableView设置不透明的统一背景色
- 只要把tableView的
backgroundColor设为和界面主背景一致的不透明颜色,别用.clear透明色,就能从根源上消除间隙的透明穿透——很多人踩这个坑就是因为把tableView背景设成了透明,系统会让临时动画层直接透出叠在空白区域上。
- 只要把tableView的
- 需要自定义间隙样式的方案:在间隙对应位置插入不透明占位视图
- 实现
UITableViewDelegate的willDisplay代理方法,在每个section的间隙区域(也就是上一个section尾视图和当前section头视图之间的空白位置),加一个和间隙高度完全一致的不透明视图,视图颜色和背景保持统一就行 - 注意这个占位视图要加到tableView的
backgroundView层级上,别和cell、头视图放到同一个交互层,不然会挡住头视图的点击手势
- 实现
- 动画层级修正:所有插入、删除行的操作必须放到批量事务里执行
- 别单独调用
insertRows/deleteRows,一定要用performBatchUpdates把所有行变更操作包裹起来,没有事务包裹的单行动画很容易出现层级错乱,让临时快照层浮到遮挡视图的上层 - 示例代码:
tableView.performBatchUpdates({ tableView.insertRows(at: rowsToInsertOrDelete, with: .top) // 或对应的删除行逻辑 tableView.deleteRows(at: rowsToInsertOrDelete, with: .top) }, completion: nil) - 别单独调用
容易踩的额外坑
- 别为了做间隙效果用plain样式的tableView硬模拟分组效果,plain样式的吸附头视图机制和grouped不一样,会进一步放大动画穿透的问题
- 自定义的分区头视图不要设成透明背景,不然头视图覆盖的区域也会出现和间隙一样的穿透效果
内容的提问来源于stack exchange,提问作者Vyachaslav Gerchicov
相关产品推荐
相关产品推荐

