You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI按钮:如何在按压动画完成后执行跳转动作?

解决方案:等待按钮动画完成后再执行跳转

要解决按钮点击后直接跳转导致看不到按压动画的问题,核心思路是让跳转动作延迟到动画完成后执行,下面提供两种可行实现方式:

方法一:固定延迟匹配动画时长

先给自定义按钮样式明确动画时长,再通过DispatchQueue延迟对应时间执行跳转:

1. 修改自定义按钮样式(明确动画时长)

struct CustomButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .foregroundColor(Color.blue)
            .padding(.vertical)
            .frame(height: 48)
            .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
            .background(Color.white)
            .cornerRadius(32)
            .scaleEffect(configuration.isPressed ? 0.9 : 1.0)
            .opacity(configuration.isPressed ? 0.6 : 1.0)
            // 明确动画时长,后续延迟时间和这个保持一致
            .animation(.easeInOut(duration: 0.2), value: configuration.isPressed)
    }
}

2. 在视图中添加延迟跳转逻辑

struct TestView: View {
    @State private var navigationPath = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            Button(action: {
                // 延迟0.2秒,确保动画完全结束后再跳转
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                    navigationPath.append("TargetView")
                }
            }, label: {
                Text("Test")
            })
            .buttonStyle(CustomButtonStyle())
            .navigationDestination(for: String.self) { _ in
                // 替换成你的目标视图
                Text("Next View")
            }
        }
    }
}

方法二:利用动画完成回调(更精准)

通过SwiftUI的动画完成回调,在缩放/透明度动画结束后触发跳转,无需依赖固定延迟:

struct TestView: View {
    @State private var navigationPath = NavigationPath()
    @State private var isButtonPressed = false
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            Button(action: {
                isButtonPressed = true
                // 执行按压恢复动画,完成后触发跳转
                withAnimation(.easeInOut(duration: 0.2)) {
                    isButtonPressed = false
                } completion: {
                    navigationPath.append("TargetView")
                }
            }, label: {
                Text("Test")
                    .foregroundColor(Color.blue)
                    .padding(.vertical)
                    .frame(height: 48)
                    .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                    .background(Color.white)
                    .cornerRadius(32)
                    .scaleEffect(isButtonPressed ? 0.9 : 1.0)
                    .opacity(isButtonPressed ? 0.6 : 1.0)
            })
            .navigationDestination(for: String.self) { _ in
                Text("Next View")
            }
        }
    }
}

两种方法对比

  • 方法一:实现简单,无需改动原有ButtonStyle结构,但动画时长修改时需要同步调整延迟时间。
  • 方法二:动画完成时机判断更精准,避免固定延迟的误差,但需要将样式逻辑从ButtonStyle移到视图层级(或通过状态传递给ButtonStyle)。

如果使用的是NavigationLink而非NavigationStack,只需将跳转逻辑替换为激活NavigationLink的绑定状态即可,核心思路一致。

内容的提问来源于stack exchange,提问作者user45723

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 16:00:30