SwiftUI数值更新时如何实现文本组件的分步序列动画效果?
SwiftUI 分步数字更新加闪烁动画实现方案
你原来的实现问题在于触发更新时直接修改了两个数字的状态,会导致视图立刻同步刷新,无法实现分步展示的效果。你可以按以下方式修改代码:
核心实现思路
- 触发更新时先计算目标值,不要直接修改视图绑定的状态变量
- 用
DispatchQueue.main.asyncAfter替代嵌套Timer实现时间序列控制,代码更简洁,也不用额外处理Timer的生命周期 - 闪烁效果直接用SwiftUI内置的重复动画实现,不用手动控制每一次透明度切换
完整可运行代码
ContentView 实现
struct ContentView: View { @State private var number1: Int = 0 @State private var number2: Int = 0 @State private var isBlinking: Bool = false var timer: Timer { Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in if Int.random(in: 0...100) < 10 { print("random event happened, increase numbers!") // 预计算目标更新值 let targetNum1 = number1 + 1 let targetNum2 = number2 + 1 // 调用序列更新方法 runUpdateSequence(num1: targetNum1, num2: targetNum2) } } } var body: some View { ZStack { SampleNumbersView( num1: number1, num2: number2, isBlinking: isBlinking ) }.onAppear { let _ = timer } } private func runUpdateSequence(num1: Int, num2: Int) { // 第一步:立刻更新第一个数字 number1 = num1 // 1秒后更新第二个数字 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { number2 = num2 // 再间隔1秒触发闪烁 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print("start blinking") // 两次完整闪烁:每次闪烁包含显示/隐藏两个阶段,所以repeatCount设为4 withAnimation(.easeInOut(duration: 0.2).repeatCount(4, autoreverses: true)) { isBlinking = true } // 闪烁结束后重置状态 DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) { isBlinking = false print("stop blinking") } } } } }
SampleNumbersView 实现
struct SampleNumbersView: View { var num1: Int = 0 var num2: Int = 0 var isBlinking: Bool = false var body: some View { VStack(spacing: 16) { Text("Number 1: \(num1)") .opacity(isBlinking ? 0 : 1) Text("Number 2: \(num2)") .opacity(isBlinking ? 0 : 1) } } }
自定义调整说明
- 如果要修改数字更新的间隔,直接调整
asyncAfter的deadline参数即可 - 如果要修改闪烁次数,调整
repeatCount的数值即可:每多一次完整闪烁增加2个计数(比如3次闪烁设为6) - 如果要修改闪烁速度,调整
duration的参数即可
内容的提问来源于stack exchange,提问作者mkto
相关产品推荐
相关产品推荐

