双UITableView联动滚动异常:首单元格顶部下拉后无法回弹
解决两个并排UITableView滚动联动时顶部单元格无法回弹的问题
我之前也遇到过一模一样的问题!这种并排TableView联动滚动的坑确实容易踩,咱们来一步步拆解原因并解决它:
问题根源
你当前的代码没有处理滚动事件循环触发的问题:当你设置另一个TableView的contentOffset时,会再次触发scrollViewDidScroll方法,两个TableView互相触发滚动回调,在顶部下拉的弹性滚动阶段,这种循环会导致偏移量被反复覆盖,最终无法正常回弹到原始位置。
另外还有一个潜在隐患:如果两个TableView的contentInset、adjustedContentInset或者contentSize不一致,也会加剧滚动偏移的异常。
修复方案
1. 添加同步标记,防止循环触发
首先添加一个私有变量来标记当前是否正在同步滚动,避免回调循环:
private var isScrollSyncing = false
2. 修改滚动回调逻辑
更新scrollViewDidScroll方法,利用标记阻断循环,同时确保同步逻辑更严谨:
func scrollViewDidScroll(_ scrollView: UIScrollView) { // 如果正在同步滚动,直接返回,避免循环触发 guard !isScrollSyncing else { return } isScrollSyncing = true // 使用defer确保标记一定会被重置 defer { isScrollSyncing = false } let targetOffset = scrollView.contentOffset if scrollView === coinNameTableView { coinInfoTableView?.setContentOffset(targetOffset, animated: false) } else if scrollView === coinInfoTableView { coinNameTableView?.setContentOffset(targetOffset, animated: false) } }
3. 统一两个TableView的滚动相关属性
在viewDidLoad或者布局完成的方法中,确保两个TableView的滚动属性一致,避免因基础设置差异导致的滚动异常:
override func viewDidLoad() { super.viewDidLoad() // 统一contentInset coinNameTableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) coinInfoTableView.contentInset = coinNameTableView.contentInset // 统一滚动行为(比如是否允许弹性滚动) coinNameTableView.bounces = true coinInfoTableView.bounces = coinNameTableView.bounces // 确保两个TableView的cell高度一致,保证contentSize匹配 coinNameTableView.rowHeight = UITableView.automaticDimension coinInfoTableView.rowHeight = coinNameTableView.rowHeight }
额外提示
如果你的TableView使用了自定义的contentInset(比如适配导航栏、TabBar),记得用adjustedContentInset来计算实际的滚动边界,避免在边界处出现异常偏移。
内容的提问来源于stack exchange,提问作者LF-DevJourney
相关产品推荐
相关产品推荐

