You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中ScrollView执行UIView动画时如何获取实时contentOffset偏移量

实现方案

UIKit 动画过程中修改的是图层的呈现层(presentation layer)属性,直接读取 scrollView.contentOffset 只能拿到动画的最终目标值,要获取实时偏移量可以用以下方案:

该方案和屏幕刷新率保持同步,取值精度最高,是最常用的实现方式:

  1. 首先声明全局的 CADisplayLink 属性:
private var displayLink: CADisplayLink?
  1. 在启动 ScrollView 动画的同时初始化监听:
// 原有的ScrollView动画代码
UIView.animate(withDuration: Double(totalMidiTime) / 1000, delay: 0, options: .curveLinear) {
    self.scrollView.contentOffset.x = self.scrollView.contentSize.width - self.leftMargin
} completion: { [weak self] (_) in
    // 动画结束后销毁监听,避免内存泄漏
    self?.displayLink?.invalidate()
    self?.displayLink = nil
}
// 启动实时监听
displayLink = CADisplayLink(target: self, selector: #selector(getRealtimeOffset))
displayLink?.add(to: .main, forMode: .common)
  1. 实现监听方法,从呈现层读取实时偏移量:
@objc private func getRealtimeOffset() {
    guard let presentationLayer = scrollView.layer.presentation() else { return }
    // presentationLayer.bounds.origin.x 就等于当前实时的contentOffset.x
    let realtimeOffsetX = presentationLayer.bounds.origin.x
    // 此处可添加你需要的业务逻辑,比如打印、联动其他视图等
    print("实时X偏移量:\(realtimeOffsetX)")
}

方案2:iOS 15+ 动画进度回调

如果最低兼容版本为iOS 15及以上,可以使用系统提供的动画进度回调API,不过该方案使用场景局限性更大,更推荐优先使用方案1。

注意事项

动画执行结束后必须调用 displayLink.invalidate() 销毁监听对象,否则会造成内存泄漏
不要直接读取 scrollView.contentOffset 作为动画过程中的实时值,该属性在动画触发时就已经被赋值为最终的目标值
scrollView.layer.presentation() 返回的是图层当前屏幕上正在渲染的实时状态,所有动画过程中的实时值都要从该对象读取

内容的提问来源于stack exchange,提问作者Norman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.19 21:15:06