SwiftUI动画:如何自定义先淡出再淡入的过渡动画?
实现旧文本淡出后再淡入新文本的方法
首先要明确:直接修改Text的字符串内容不会触发.transition动画,因为视图本身没有被插入或移除。要实现文本切换的淡入淡出,需要通过条件渲染切换不同的Text视图,才能触发过渡动画。
要达成「旧值完全淡出后再淡入新值」的效果,无需完全自定义Transition,使用SwiftUI内置的**不对称过渡(asymmetric transition)**即可实现,核心思路是给新视图的插入动画设置等于旧视图移除动画时长的延迟,让旧视图的淡出动画完成后,再启动新视图的淡入动画。
方法一:手动控制动画时序
import SwiftUI struct TextFadeSequenceView: View { @State private var currentText: String = "初始文本" @State private var isShowingNewText: Bool = false // 统一设置动画时长,方便后续调整 private let animationDuration: Double = 0.6 var body: some View { VStack(spacing: 20) { // 通过条件渲染切换文本视图,触发过渡动画 if isShowingNewText { Text(currentText) .transition(.opacity.delay(animationDuration)) } else { Text(currentText) .transition(.opacity) } Button("切换文本") { // 先隐藏当前文本,触发淡出动画 isShowingNewText = false // 等待淡出动画完成后,更新文本并显示新内容 DispatchQueue.main.asyncAfter(deadline: .now() + animationDuration) { currentText = "新文本 \(Int.random(in: 1...100))" isShowingNewText = true } } } .animation(.easeInOut(duration: animationDuration), value: isShowingNewText) .padding() } } struct TextFadeSequenceView_Previews: PreviewProvider { static var previews: some View { TextFadeSequenceView() } }
方法二:使用不对称过渡(更简洁)
直接通过.asymmetric定义插入和移除的动画规则,无需手动延迟:
import SwiftUI struct TextFadeSequenceView: View { @State private var currentText: String = "初始文本" @State private var toggleView: Bool = false private let animationDuration: Double = 0.6 var body: some View { VStack(spacing: 20) { Group { if toggleView { Text(currentText) } else { Text(currentText) } } .transition( .asymmetric( // 新视图插入动画:延迟等于移除时长,确保旧视图完全消失后再淡入 insertion: .opacity.animation(.easeInOut(duration: animationDuration).delay(animationDuration)), // 旧视图移除动画:正常淡出 removal: .opacity.animation(.easeInOut(duration: animationDuration)) ) ) Button("切换文本") { toggleView.toggle() // 同步更新文本内容,状态切换会自动触发视图的移除与插入 currentText = "新文本 \(Int.random(in: 1...100))" } } .padding() } }
核心原理
- 不对称过渡(
.asymmetric)分别定义了视图插入和移除阶段的动画行为:- 移除动画:旧文本在设定时长内从完全可见变为透明,完成淡出。
- 插入动画:新文本延迟与移除时长相等的时间后,从透明变为完全可见,实现淡入。
- 通过条件渲染(
if/else)切换视图,触发SwiftUI的过渡动画机制,从而实现严格的「先淡出旧文本,再淡入新文本」的顺序效果。
内容的提问来源于stack exchange,提问作者horseshoe7
相关产品推荐
相关产品推荐

