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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 04:57:12