Swift自定义下拉刷新实现:替换UIRefreshControl默认加载指示器
问题原因
你当前同时出现两个加载指示器的核心原因是:
- 你没有隐藏
UIRefreshControl自带的默认系统加载指示器 - 自定义
ProgressView的约束锚定对象错误,且UIRefreshControl的添加方式不符合系统规范
具体修复步骤
1. 隐藏系统默认加载指示器
系统UIRefreshControl自带的加载指示器可以通过设置tintColor为透明直接隐藏,不需要修改视图层级。
2. 修正UIRefreshControl的添加方式
不要直接调用tableView.addSubview(refreshControl),iOS的UITableView已经内置了refreshControl属性,直接赋值即可,避免出现层级异常。
3. 修正自定义加载指示器的约束
自定义ProgressView作为refreshControl的子控件,应该锚定到refreshControl的中心位置,而不是tableView的顶部,保证下拉过程中指示器会跟随滑动位置同步移动。
修改后代码示例
首先修改setupRefreshControl方法:
func setupRefreshControl(){ // 隐藏系统默认指示器 refreshControl.tintColor = .clear // 自定义指示器添加到refreshControl上 refreshControl.addSubview(loadingIndicator) // 直接赋值给tableView的内置属性,不要手动addSubview tableView.refreshControl = refreshControl setupLoadingIndicator() refreshControl.addTarget(self, action: #selector(forceRefreshGames), for: .valueChanged) }
然后修改setupLoadingIndicator方法的约束锚定对象:
func setupLoadingIndicator(){ NSLayoutConstraint.activate([ loadingIndicator.centerXAnchor.constraint(equalTo: refreshControl.centerXAnchor), loadingIndicator.centerYAnchor.constraint(equalTo: refreshControl.centerYAnchor), loadingIndicator.widthAnchor.constraint(equalToConstant: 50), loadingIndicator.heightAnchor.constraint(equalTo: loadingIndicator.widthAnchor) ]) }
最后调整刷新逻辑的动画启停时机,避免无意义的性能消耗:
@objc func forceRefreshGames() { // 下拉触发刷新时启动自定义动画 loadingIndicator.isAnimating = true // 此处执行你的刷新业务逻辑,比如网络请求 // ... // 刷新完成后先停止自定义动画,再结束refreshControl的刷新状态 DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // 此处为模拟刷新耗时的示例 self.loadingIndicator.isAnimating = false self.refreshControl.endRefreshing() } }
兼容性优化
如果部分iOS版本下系统指示器仍未完全隐藏,可以额外遍历refreshControl的子视图手动隐藏系统加载控件:
refreshControl.subviews.forEach { subview in if subview is UIActivityIndicatorView { subview.isHidden = true } }
内容的提问来源于stack exchange,提问作者Noah Iarrobino
相关产品推荐
相关产品推荐

