如何在多section场景下实现可随滚动显隐的sticky headerTableView
实现非粘性自定义Header随列表滚动动态显隐的方案
核心实现思路
不要依赖系统plain样式的粘性特性,把自定义的headerTableView作为独立视图添加到tableView的父视图上,层级置于tableView顶部,通过监听tableView的滚动偏移量动态计算header的显隐状态和位置,完全脱离系统section header的逻辑,就不会影响其他section的header表现。
具体实现步骤
- 第一步:视图层级搭建
不要把headerTableView设置为tableView的tableHeaderView,也不要作为section的header视图,直接添加到tableView所在的父容器上,固定宽和父视图一致,初始位置顶在父视图顶部,设置好初始高度(比如44pt)。同时给tableView设置顶部的contentInset,值等于header的初始高度,避免列表顶部内容被header遮挡。 - 第二步:监听滚动偏移量
实现UIScrollViewDelegate的scrollViewDidScroll:方法,记录上一次的滚动偏移量lastContentOffsetY,每次滚动时计算当前和上一次偏移的差值,判断滚动方向:// 示例OC代码,Swift逻辑完全一致 CGFloat offsetDiff = scrollView.contentOffset.y - self.lastContentOffsetY; // 忽略下拉刷新的负数偏移区间,避免下拉时误触发header显隐 if (scrollView.contentOffset.y < 0) { return; } // 滚动阈值,避免小幅度滑动误触发,可自行调整数值 CGFloat threshold = 10; if (offsetDiff > threshold) { // 向下滚动,隐藏header CGFloat targetY = -self.headerView.bounds.size.height; if (self.headerView.frame.origin.y > targetY) { self.headerView.frame = CGRectMake(0, MAX(targetY, self.headerView.frame.origin.y - offsetDiff), self.headerView.bounds.size.width, self.headerView.bounds.size.height); // 同步调整tableView的contentInset.top,避免header隐藏后列表顶部出现空白 self.tableView.contentInset = UIEdgeInsetsMake(MAX(0, self.tableView.contentInset.top - offsetDiff), 0, 0, 0); } } else if (offsetDiff < -threshold) { // 向上滚动,显示header if (self.headerView.frame.origin.y < 0) { self.headerView.frame = CGRectMake(0, MIN(0, self.headerView.frame.origin.y - offsetDiff), self.headerView.bounds.size.width, self.headerView.bounds.size.height); self.tableView.contentInset = UIEdgeInsetsMake(MIN(self.headerView.bounds.size.height, self.tableView.contentInset.top - offsetDiff), 0, 0, 0); } } // 更新上次滚动偏移量 self.lastContentOffsetY = scrollView.contentOffset.y; - 第三步:边界优化
当滚动停止时如果header处于半隐半现的状态,可以在scrollViewDidEndDragging:willDecelerate:和scrollViewDidEndDecelerating:方法中增加吸附逻辑,根据当前露出的高度判断是完全展示还是完全收起,提升交互流畅度。 - 第四步:兼容其他section header
此时tableView可以直接设置为grouped样式,原生的section header不会有粘性效果;如果需要部分section header实现粘性,也可以单独写自定义粘性逻辑,和顶部headerTableView的逻辑完全隔离,互不影响。
方案优势
- 完全不受列表滚动位置限制,不管滑到列表的哪个位置,只要向上滑动就显示header,向下滑动就隐藏,不需要回到列表顶部才触发效果
- 不会影响其他section header的样式和行为,粘性/非粘性的section header都可以单独实现
- 动画可自由控制,显隐速度、触发阈值都可以自行调整,也可以额外叠加透明度渐变、缩放等自定义动效
内容的提问来源于stack exchange,提问作者aleksy.t
相关产品推荐
相关产品推荐

