Sheet视图内NavigationLink点击无响应问题求助
Sheet 视图内完全允许使用 NavigationLink,你遇到的真机无响应问题,核心原因是导航层级的归属问题:
根视图的 NavigationStack 只负责管理自身层级内的视图,而通过 sheet 弹出的模态视图属于独立的层级,不在根导航栈的管辖范围内。预览环境可能因为模拟机制临时创建了导航栈,所以看似正常,但真机上没有对应的导航栈来承载跳转,导致点击无反应。
下面提供两种可行的解决方案:
方案一:在 Sheet 内容内部嵌套 NavigationStack
直接在你的 PlusMenu 视图外层包裹一个 NavigationStack,让 Sheet 拥有自己的导航栈:
struct PlusMenu: View { @Environment(\.dismiss) var dismiss @State var scaleChange = true var buttons = ["cup.and.saucer", "takeoutbag.and.cup.and.straw", "carrot", "fork.knife","equal.square"] var body: some View { NavigationStack { // 新增导航栈 VStack{ HStack{ Spacer() Button(action: { dismiss() }, label: { Text("Cancel") .font(customFont(20, "-Black")) }) .foregroundColor(.black) .padding(.top) } LabelledDivider(label: "Actions") Spacer() buttonList(start:0, end: 3) buttonList(start:3, end:buttons.count) Spacer() } .padding(.horizontal) } } func buttonList(start:Int, end:Int) -> some View{ HStack{ ForEach(buttons[start..<end], id:\.self){ buttonName in Spacer() NavigationLink { Text("Enter") } label: { Image(systemName: buttonName) .padding() .background(Circle().stroke(.semiGray, lineWidth: 3).shadow(radius: 3)) .foregroundColor(.black) } Spacer() } } .padding(.vertical) } }
这种方案的特点是:跳转后的页面属于 Sheet 自身的导航流程,返回时会先回到 Sheet,再关闭 Sheet,适合独立的模态内操作流程。
方案二:通过回调让根导航栈处理跳转
如果希望跳转后的页面归属于根视图的导航流程,可以把跳转逻辑交给根视图处理:
第一步:修改 PlusMenu,添加回调闭包
struct PlusMenu: View { @Environment(\.dismiss) var dismiss @State var scaleChange = true var buttons = ["cup.and.saucer", "takeoutbag.and.cup.and.straw", "carrot", "fork.knife","equal.square"] var onButtonTap: (String) -> Void // 新增回调,传递按钮标识 var body: some View { VStack{ // 原有内容不变 HStack{ Spacer() Button(action: { dismiss() }, label: { Text("Cancel") .font(customFont(20, "-Black")) }) .foregroundColor(.black) .padding(.top) } LabelledDivider(label: "Actions") Spacer() buttonList(start:0, end: 3) buttonList(start:3, end:buttons.count) Spacer() } .padding(.horizontal) } func buttonList(start:Int, end:Int) -> some View{ HStack{ ForEach(buttons[start..<end], id:\.self){ buttonName in Spacer() Button(action: { dismiss() onButtonTap(buttonName) // 点击时通知根视图 }) { Image(systemName: buttonName) .padding() .background(Circle().stroke(.semiGray, lineWidth: 3).shadow(radius: 3)) .foregroundColor(.black) } Spacer() } } .padding(.vertical) } }
第二步:在根视图中处理跳转逻辑
struct RootView: View { @State private var showSheet = false @State private var navigationPath = NavigationPath() var body: some View { NavigationStack(path: $navigationPath) { Button("打开菜单") { showSheet = true } .sheet(isPresented: $showSheet) { PlusMenu { buttonName in // 根据按钮标识决定跳转目标 switch buttonName { case "cup.and.saucer": navigationPath.append(DrinkView()) case "takeoutbag.and.cup.and.straw": navigationPath.append(TakeoutView()) default: navigationPath.append(Text("Enter")) } } } .navigationDestination(for: Text.self) { textView in textView } .navigationDestination(for: DrinkView.self) { _ in Text("饮品页面") } .navigationDestination(for: TakeoutView.self) { _ in Text("外卖页面") } } } // 定义示例视图 struct DrinkView: Hashable {} struct TakeoutView: Hashable {} }
这种方案的特点是:关闭 Sheet 后直接进入目标页面,跳转的页面属于根导航栈的一部分,适合需要融入主流程的场景。
内容的提问来源于stack exchange,提问作者Ting Qu
相关产品推荐
相关产品推荐

