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

如何在UI滑块动画过程中获取其实际值?

我完全懂你的痛点——给UI滑块做动画时,它直接跳到最终值,根本没法像Android里的onProgressChanged那样,实时获取动画过程中的每一步进度值。别慌,这里有两个实用的解决方案,帮你实现实时监听滑块动画进度的需求:

方案1:用CADisplayLink逐帧控制(最灵活)

CADisplayLink会跟屏幕刷新率同步触发回调,能精准控制每一秒的滑块值变化,完全模拟Android的实时进度回调逻辑:

  • 先定义几个关键变量:动画总时长、起始值、结束值,还有CADisplayLink实例和动画开始时间
  • 创建CADisplayLink并绑定到更新方法,把它加到主运行循环里
  • 在更新方法里计算已流逝的时间,算出当前进度,实时设置滑块的value,同时在这里写你的进度响应逻辑

示例代码(Swift):

// 全局/类内变量
var displayLink: CADisplayLink?
var animationStartTime: CFTimeInterval = 0
let animationDuration: TimeInterval = 2.0 // 动画持续2秒
let sliderStartValue: Float = 0.0
let sliderEndValue: Float = 1.0
@IBOutlet weak var slider: UISlider!

// 启动滑块动画的方法
func startSliderAnimation() {
    animationStartTime = CACurrentMediaTime()
    displayLink = CADisplayLink(target: self, selector: #selector(updateSliderProgress(_:)))
    displayLink?.add(to: .main, forMode: .common)
}

// 逐帧更新滑块的回调
@objc private func updateSliderProgress(_ link: CADisplayLink) {
    let elapsedTime = CACurrentMediaTime() - animationStartTime
    
    // 动画结束后清理资源
    guard elapsedTime <= animationDuration else {
        displayLink?.invalidate()
        displayLink = nil
        slider.value = sliderEndValue
        return
    }
    
    // 计算当前进度(这里是线性变化,你可以换成缓动函数比如EaseInOut)
    let progress = Float(elapsedTime / animationDuration)
    let currentValue = sliderStartValue + (sliderEndValue - sliderStartValue) * progress
    
    // 实时设置滑块值
    slider.value = currentValue
    
    // 这里就是你的"onProgressChanged"逻辑,想干嘛就干嘛
    print("当前滑块实时值:\(currentValue)")
}
方案2:用UIViewPropertyAnimator(iOS 10+,支持系统动画曲线)

如果你想用上系统自带的动画曲线(比如淡入淡出、减速),可以用UIViewPropertyAnimator,它支持监听动画进度的变化:

@IBOutlet weak var slider: UISlider!
let sliderStartValue: Float = 0.0
let sliderEndValue: Float = 1.0

func startAnimatedSlider() {
    // 创建动画器,设置时长和曲线
    let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeInOut) {
        // 这里留空,我们手动控制进度
    }
    
    // 添加完成回调,确保滑块最终停在目标值
    animator.addCompletion { _ in
        self.slider.value = self.sliderEndValue
    }
    
    // 添加进度监听,每帧更新滑块值
    animator.addProgressObserver(interval: 1/60) { [weak self] progress in
        guard let self = self else { return }
        let currentValue = self.sliderStartValue + (self.sliderEndValue - self.sliderStartValue) * Float(progress)
        self.slider.value = currentValue
        
        // 实时响应进度变化
        print("当前滑块进度:\(currentValue)")
    }
    
    // 启动动画
    animator.startAnimation()
}
为什么之前的动画会直接跳?

你之前应该用的是UIView.animate直接设置slider.value = 目标值——这种方式是系统直接修改滑块的图层属性做动画,并不会实时更新滑块的value属性,所以你拿不到中间的进度值,看起来就像是直接跳过去了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:31:57