如何为Swift中的.transition设置动画时长以减慢过渡效果?
问题描述
在ContentView中切换session.currentState时,.transition动画速度过快,想要减慢动画速度,但发现AnyTransition没有类似duration的方法。尝试使用.animation修饰符,仍无法为指定的.transition添加时长。当前动画效果为底部滑入的快速切换。
代码片段:
struct ContentView: View { @EnvironmentObject var session: SessionManager var body: some View { ZStack { switch session.currentState { case .loggedIn: TabBar() .transition(.move(edge: .bottom)) case .onboardingSetup: OnboardingSetupView(action: session.completeOnboardingSetup) .animation(.easeInOut, value: 0.5) case .onboarding: OnboardingView(action: session.completeOnboarding) .transition( .move(edge: .bottom) ) default: ProgressView() } } .animation(.easeInOut, value: session.currentState) .onAppear(perform: session.configureCurrentState) } }
尝试为以下代码块的动画添加时长但未成功:
case .onboarding: OnboardingView(action: session.completeOnboarding) .transition( .move(edge: .bottom) )
解决方案
SwiftUI中,transition的动画时长由作用在容器上的.animation修饰符统一控制,而非直接给transition设置参数。你需要创建指定时长的Animation实例替换默认配置:
1. 统一控制所有transition的动画时长
替换ZStack上的.animation修饰符,传入带时长的动画配置:
.animation(.easeInOut(duration: 0.8), value: session.currentState)
这里的duration: 0.8即为动画持续时长(单位:秒),可根据需求调整数值。同时要移除单个View上多余的.animation修饰符(比如之前给OnboardingSetupView添加的),避免动画行为混乱。
调整后的完整代码:
struct ContentView: View { @EnvironmentObject var session: SessionManager var body: some View { ZStack { switch session.currentState { case .loggedIn: TabBar() .transition(.move(edge: .bottom)) case .onboardingSetup: OnboardingSetupView(action: session.completeOnboardingSetup) case .onboarding: OnboardingView(action: session.completeOnboarding) .transition(.move(edge: .bottom)) default: ProgressView() } } // 自定义时长的动画,统一控制所有transition .animation(.easeInOut(duration: 0.8), value: session.currentState) .onAppear(perform: session.configureCurrentState) } }
2. 为不同transition设置单独时长
如果需要让某个状态切换的动画时长和其他场景不同,可以在状态修改时用withAnimation包裹,精准指定动画参数:
class SessionManager: ObservableObject { @Published var currentState: SessionState = .default func completeOnboarding() { // 给onboarding切换到其他状态设置单独的动画时长 withAnimation(.easeInOut(duration: 1.2)) { currentState = .onboardingSetup } } // 其他状态切换使用不同时长 func completeOnboardingSetup() { withAnimation(.easeInOut(duration: 0.5)) { currentState = .loggedIn } } }
这种方式不需要在View层级添加多余的.animation修饰符,能更灵活地控制每个状态切换的动画表现。
内容的提问来源于stack exchange,提问作者lovemyreves
相关产品推荐
相关产品推荐

