UIView.animate动画锁屏或切后台后停止,有什么替代实现方案?
iOS UIView 动画切后台/锁屏解锁后停止的解决方法
问题根因
这是iOS系统的默认行为:应用进入后台或锁屏时,系统会自动移除所有视图Layer上附着的动画,回到前台后不会自动恢复,因此动画会直接停止。
解决方案
因为你的三个关联动画需要和计数器同步,核心思路是监听应用回到前台的通知,每次进入前台时按照当前计数器的进度重新启动动画,保证三者同步。
步骤1:封装可对齐进度的动画启动方法
把三个动画的逻辑统一封装到独立方法中,通过当前计数器的剩余时间计算动画启动偏移量,避免重启动画后和计数器不同步:
// 这里假设你持有当前倒计时剩余时间的变量:remainingCountdown,单位为秒 @objc func restartFocusAnimations() { // 先清理所有残留的旧动画,避免冲突 mainFocusLabel.layer.removeAllAnimations() // 另外两个关联动画对应的视图/图层也在这里清理旧动画,示例: // glowEffectLayer.removeAllAnimations() // fadeAnimateView.layer.removeAllAnimations() // 动画总周期是20秒:10秒放大 + 10秒缩小 let totalCycle: TimeInterval = 20 // 计算当前已走的时长,对总周期取余得到当前动画位置 let elapsedTime = totalCycle - remainingCountdown.truncatingRemainder(dividingBy: totalCycle) // 计算负延迟,让动画直接从当前进度开始播放,而不是从头开始 let startOffset = -elapsedTime // 重启缩放动画 UIView.animateKeyframes(withDuration: 10, delay: startOffset, options: [.autoreverse, .repeat, .beginFromCurrentState]) { UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0) { // 如果要作用于MainFocusStack,替换为对应的StackView实例即可 self.mainFocusLabel.transform = CGAffineTransform(scaleX: 1.3, y: 1.3) } } // 同步启动另外两个关联动画,使用相同的startOffset保证三者和计数器完全对齐 // 这里补充你的发光效果、透明度变化动画代码即可 }
步骤2:监听前台通知,自动重启动画
在视图生命周期中添加通知监听,应用每次回到前台时自动调用上面的动画重启方法:
override func viewDidLoad() { super.viewDidLoad() // 监听应用即将进入前台的通知 NotificationCenter.default.addObserver( self, selector: #selector(restartFocusAnimations), name: UIApplication.willEnterForegroundNotification, object: nil ) // 页面加载完成后首次启动动画 restartFocusAnimations() } // 页面销毁时移除通知,避免内存泄漏 deinit { NotificationCenter.default.removeObserver( self, name: UIApplication.willEnterForegroundNotification, object: nil ) }
注意事项
- 动画参数添加
.beginFromCurrentState,可避免动画重启时出现视觉跳变 - 如果你的计数器进入后台会暂停,可在收到
UIApplication.didEnterBackgroundNotification通知时记录当前的动画进度,回到前台时用记录的进度计算startOffset即可 - 三个关联动画必须在同一个方法内同步启动,使用相同的
startOffset参数,保证三者完全同步
内容的提问来源于stack exchange,提问作者Rem Biths Wind
相关产品推荐
相关产品推荐

