如何在Xcode中用Swift为APP各页面添加顶部绿色进度追踪条
嘿,这个需求很实用啊!我来分享两种常见的实现方式,一种是全局页面浏览进度追踪(比如用户访问过的页面数占总页面数的比例),另一种是单个页面内的滚动进度追踪,你可以根据实际需求选~
方式一:全局页面浏览进度追踪
这种方式适合你想让用户看到自己在整个应用里已经浏览了多少页面的场景,比如多步骤引导流程,或是统计用户探索应用的深度。
1. 创建全局进度管理单例
首先需要一个单例来统一管理已访问页面数和总页面数,让所有页面共享进度数据:
import UIKit class ProgressManager { static let shared = ProgressManager() // 总页面数,你可以根据应用实际情况设置 var totalPages: Int = 5 // 用Set存储已访问页面,避免重复进入同一页面重复计数 private(set) var visitedPages: Set<String> = [] private init() {} // 标记页面为已访问,传入页面的唯一标识(比如ViewController类名) func markPageAsVisited(pageIdentifier: String) { visitedPages.insert(pageIdentifier) } // 计算当前进度:已访问数 / 总页面数 func currentProgress() -> CGFloat { guard totalPages > 0 else { return 0 } return CGFloat(visitedPages.count) / CGFloat(totalPages) } }
2. 创建自定义进度条View
做一个可复用的绿色进度条View,方便在每个页面快速添加:
import UIKit class ProgressBarView: UIView { // 实际显示进度的绿色子视图 private let progressView = UIView() override init(frame: CGRect) { super.init(frame: frame) setupView() } required init?(coder: NSCoder) { super.init(coder: coder) setupView() } private func setupView() { backgroundColor = .lightGray // 进度条背景色 progressView.backgroundColor = .systemGreen // 进度填充色 addSubview(progressView) // 设置AutoLayout约束 progressView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ progressView.leadingAnchor.constraint(equalTo: leadingAnchor), progressView.topAnchor.constraint(equalTo: topAnchor), progressView.bottomAnchor.constraint(equalTo: bottomAnchor), progressView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0) // 初始进度为0 ]) } // 更新进度的方法,传入0-1之间的数值 func updateProgress(to progress: CGFloat) { let clampedProgress = max(0, min(1, progress)) // 确保进度在合法范围 progressView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: clampedProgress).isActive = true // 添加平滑动画 UIView.animate(withDuration: 0.3) { self.layoutIfNeeded() } } }
3. 在ViewController中集成进度条
为了避免重复写代码,我们可以创建一个基类ViewController,让所有需要显示进度条的页面都继承它:
import UIKit class BaseViewController: UIViewController { private let progressBar = ProgressBarView() override func viewDidLoad() { super.viewDidLoad() setupProgressBar() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 标记当前页面为已访问,用类名作为唯一标识 let pageId = String(describing: type(of: self)) ProgressManager.shared.markPageAsVisited(pageIdentifier: pageId) // 更新进度条 let progress = ProgressManager.shared.currentProgress() progressBar.updateProgress(to: progress) } private func setupProgressBar() { progressBar.translatesAutoresizingMaskIntoConstraints = false view.addSubview(progressBar) NSLayoutConstraint.activate([ progressBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), progressBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), progressBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), progressBar.heightAnchor.constraint(equalToConstant: 4) // 进度条高度 ]) } }
之后你的业务页面只需要继承这个基类即可:
class HomeViewController: BaseViewController { // 你的页面业务逻辑... }
方式二:单个页面内的滚动进度追踪
如果你的需求是追踪用户在当前页面的滚动进度(比如TableView、WebView的滚动),可以用下面的方式:
1. 复用自定义ProgressBarView
直接使用我们之前创建的ProgressBarView即可。
2. 在滚动页面中集成(以TableView为例)
在ViewController中添加进度条,并监听滚动事件:
import UIKit class ScrollableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { private let progressBar = ProgressBarView() private let tableView = UITableView() override func viewDidLoad() { super.viewDidLoad() setupProgressBar() setupTableView() } private func setupProgressBar() { progressBar.translatesAutoresizingMaskIntoConstraints = false view.addSubview(progressBar) NSLayoutConstraint.activate([ progressBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), progressBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), progressBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), progressBar.heightAnchor.constraint(equalToConstant: 4) ]) } private func setupTableView() { tableView.delegate = self tableView.dataSource = self tableView.frame = view.bounds tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") view.addSubview(tableView) } // MARK: - UITableView 代理方法 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row + 1)" return cell } // 监听滚动事件,计算进度 func scrollViewDidScroll(_ scrollView: UIScrollView) { let maximumScrollOffset = scrollView.contentSize.height - scrollView.bounds.height guard maximumScrollOffset > 0 else { progressBar.updateProgress(to: 0) return } let progress = scrollView.contentOffset.y / maximumScrollOffset progressBar.updateProgress(to: progress) } }
如果是WebView,只需要监听webViewDidScroll方法,进度计算逻辑和TableView一致。
一些优化建议
- 样式自定义:你可以修改
ProgressBarView的圆角、颜色、高度,让它更贴合APP的设计风格。 - 全局进度灵活性:如果应用页面数量不固定,可以在
ProgressManager中动态设置totalPages,或是根据导航栈的长度计算进度。 - 避免重复计数:全局进度方式中,用
Set存储已访问页面能有效避免重复进入同一页面时的进度重复累加。
内容的提问来源于stack exchange,提问作者Asif Iqbal
相关产品推荐
相关产品推荐

