如何通过触摸中断UIViewPropertyAnimator动画?触摸事件延迟响应问题
解决UIViewPropertyAnimator动画过程中触摸事件不响应的问题
这个问题我做交互动画时也踩过坑!核心原因是UIViewPropertyAnimator默认会在动画执行期间禁用目标视图的用户交互,所以你的touchesBegan方法在动画跑起来的时候根本收不到触摸事件,只有等动画结束后才会触发。
解决步骤
启用动画期间的用户交互
创建动画对象时,必须设置isUserInteractionEnabled = true,这是让视图在动画过程中能响应触摸的关键。在
touchesBegan中处理动画中断逻辑- 先判断是否有正在运行的动画
- 如果有,立即中断当前动画,并将视图透明度恢复为1
- 如果没有,启动透明度变为0的动画
完整代码示例
import UIKit class ViewController: UIViewController { // 保存动画对象的引用,用于判断状态和中断 private var fadeAnimator: UIViewPropertyAnimator? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBlue } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesBegan(touches, with: event) if let runningAnimator = fadeAnimator, runningAnimator.isRunning { // 1. 中断当前正在运行的动画,参数true表示将视图属性更新到动画当前的中间状态 runningAnimator.stopAnimation(true) // 2. 快速将透明度恢复为1 UIView.animate(withDuration: 0.3) { self.view.alpha = 1.0 } // 3. 重置动画对象,避免后续判断出错 fadeAnimator = nil } else { // 1. 创建透明度变为0的动画 fadeAnimator = UIViewPropertyAnimator(duration: 2.0, curve: .linear) { self.view.alpha = 0.0 } // 2. 关键设置:允许动画期间的用户交互 fadeAnimator?.isUserInteractionEnabled = true // 3. 启动动画 fadeAnimator?.startAnimation() // 4. 动画结束后重置动画对象 fadeAnimator?.addCompletion { _ in self.fadeAnimator = nil } } } }
额外说明
stopAnimation(_:)方法的参数true会立即把视图的属性更新到动画当前的进度位置,之后我们用一个短动画恢复透明度,体验会更流畅。- 如果你想让中断后的恢复动画和原动画的节奏一致,也可以用
continueAnimation(withTimingParameters:durationFactor:)让动画反向播放,不过直接用快速动画恢复的方式更直观。 - 确保你的目标视图(以及父视图)的
isUserInteractionEnabled默认是true(一般默认都是开启的,除非你手动关闭过)。
内容的提问来源于stack exchange,提问作者PrepareFor
相关产品推荐
相关产品推荐

