如何监听UITableView scrollToRow动画完成时机以修复高亮失效?
解决UITableView scrollToRow动画完成后执行高亮操作的问题
你的推测完全正确——scrollToRow的滚动动画和高亮动画同时执行时,不仅可能因为目标cell还未进入可视区域,导致cellForRow(at:)返回nil,还会因为动画并行干扰,直接让高亮效果失效。要解决这个问题,你可以通过UIScrollView的代理方法精准捕获滚动动画的完成时机,等滚动彻底结束后再执行高亮逻辑。
具体实现步骤
- 让你的ViewController遵守
UIScrollViewDelegate协议(UITableView继承自UIScrollView,直接兼容该协议) - 声明一个可选的
IndexPath属性,用来暂存需要高亮的目标行索引 - 调用
scrollToRow时先保存目标索引,再执行滚动操作 - 在滚动动画结束的代理方法中,执行高亮代码
修改后的完整代码示例
// 在ViewController类中添加属性,暂存需要高亮的索引 var pendingHighlightIndexPath: IndexPath? // 触发滚动并准备高亮的逻辑 DispatchQueue.main.async { self.pendingHighlightIndexPath = indexPath self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true) } // 扩展ViewController实现UIScrollView代理方法 extension YourViewController: UIScrollViewDelegate { func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { // 校验目标索引和cell有效性 guard let targetIndexPath = pendingHighlightIndexPath, let cell = tableView.cellForRow(at: targetIndexPath) as? NewsItemCell else { pendingHighlightIndexPath = nil return } // 创建并执行高亮动画 let highlightView = UIView(frame: cell.contentView.bounds) // 用bounds避免布局偏移问题 highlightView.backgroundColor = .white highlightView.alpha = 0.0 cell.contentView.addSubview(highlightView) UIView.animate(withDuration: 1.0, delay: 0, options: .curveEaseIn) { highlightView.alpha = 1.0 } completion: { _ in UIView.animate(withDuration: 1.5, delay: 0, options: .curveEaseOut) { highlightView.alpha = 0.0 } completion: { _ in highlightView.removeFromSuperview() } } // 重置暂存的索引,避免重复触发 pendingHighlightIndexPath = nil } }
额外注意事项
- 确保在
viewDidLoad中设置tableView.delegate = self,否则代理方法不会被触发 - 用
contentView.bounds替代frame创建高亮视图,能避免cell布局变化时出现视图偏移 - 每次执行高亮后重置
pendingHighlightIndexPath,防止多次滚动操作时出现逻辑混乱
内容的提问来源于stack exchange,提问作者Vileriu
相关产品推荐
相关产品推荐

