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

SwiftUI中自定义Button绑定NavigationLink无法跳转iOS问题

解决SwiftUI中自定义按钮嵌套NavigationLink无法跳转的问题

问题原因

你的CircleButtonWithIcon内部封装了一个Button组件,当把它作为NavigationLink的label使用时,点击事件会被内部的Button优先拦截并消耗,导致外层NavigationLink的跳转逻辑无法触发。

解决方案

方案1:移除自定义按钮内部的Button(最简单)

直接把CircleButtonWithIcon改成纯视图组件,让NavigationLink负责处理点击跳转逻辑:

struct CircleButtonWithIcon: View {
    // 移除无用的@State变量
    var body: some View {
        Image(systemName: "arrow.right")
            .font(.system(size: 24))
            .foregroundColor(.white)
            .padding(20)
            .background(Color(#colorLiteral(red: 1, green: 0.3607843137, blue: 0.003921568627, alpha: 1)))
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(Color.white, lineWidth: 3)
            )
    }
}

修改后,原来的WelcomeView中的NavigationLink就能正常响应点击跳转了。

方案2:给自定义按钮添加Action闭包(保留内部Button)

如果需要保留自定义按钮内部的Button(比如要添加点击动画、额外逻辑),可以给组件添加一个外部可传入的action闭包,通过绑定状态触发NavigationLink跳转:

首先修改CircleButtonWithIcon:

struct CircleButtonWithIcon: View {
    let action: () -> Void // 定义外部传入的action闭包
    
    var body: some View {
        Button(action: action) { // 将闭包绑定到内部Button的action
            Image(systemName: "arrow.right")
                .font(.system(size: 24))
                .foregroundColor(.white)
                .padding(20)
                .background(Color(#colorLiteral(red: 1, green: 0.3607843137, blue: 0.003921568627, alpha: 1)))
                .clipShape(Circle())
                .overlay(
                    Circle()
                        .stroke(Color.white, lineWidth: 3)
                )
        }
    }
}

然后修改WelcomeView,使用isActive绑定的NavigationLink:

struct WelcomeView: View {
    @State private var navigateToHomePage = false

    var body: some View {
        NavigationView {
            ZStack {
                Image("WelcomeBackground")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .edgesIgnoringSafeArea(.all)
                
                VStack(alignment: .center) {
                    Spacer()
                    ZStack(alignment: .center) {
                        VStack {
                            VStack {
                                HStack {
                                    Text("No Worry,")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .fontWeight(.bold)
                                    Text("Handle")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .fontWeight(.regular)
                                }
                                HStack {
                                    Text("Your Hunger,")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .fontWeight(.regular)
                                    Text("With")
                                        .font(.title)
                                        .foregroundColor(.white)
                                        .fontWeight(.bold)
                                }
                                Text("Eattak!")
                                    .font(.title)
                                    .foregroundColor(.white)
                                    .fontWeight(.bold)
                                                            
                                Text("Eattak come to help you hunger problem with easy find any restaurant")
                                    .font(.body)
                                    .foregroundColor(.white).padding().multilineTextAlignment(.center)
                            }
                            .padding()
                            
                            // 使用isActive绑定的NavigationLink,用EmptyView隐藏默认label
                            NavigationLink(destination: HomeView(), isActive: $navigateToHomePage) {
                                EmptyView()
                            }
                            
                            // 传入自定义按钮的点击逻辑,修改状态触发跳转
                            CircleButtonWithIcon(action: {
                                navigateToHomePage = true
                            })
                        }
                        .padding(.bottom,100)
                    }
                }
                .background(
                    Image("welcome-black-shadow")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .frame(minWidth: 0, maxWidth: .infinity)
                )
                .foregroundColor(.white)
                .padding(.horizontal, 24)
            }
        }
    }
}

关键逻辑说明

SwiftUI的手势响应遵循内层优先原则,当视图嵌套时,内层的可交互组件(比如Button)会优先接收并处理点击事件,外层的交互组件(比如NavigationLink)无法再响应同一点击。因此要么移除内层的可交互组件,要么通过状态绑定的方式绕开手势拦截问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 14:42:26