SwiftUI中自定义Button绑定NavigationLink无法跳转iOS问题
问题原因
你的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
相关产品推荐
相关产品推荐

