如何在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
相关产品推荐
相关产品推荐

