SwiftUI上下文菜单导航到另一个视图。

7
我正在尝试使用以下代码使上下文菜单导航到另一个视图
var body: some View
{
    VStack
    {
        Text(self.event.name).font(.body)
        ...
        Spacer()
        NavigationLink(destination: EditView(event: self.event))
        {
            Image(systemName: "pencil")
        }
    }
    .navigationBarTitle(Text(appName))
    .contextMenu
    {
        NavigationLink(destination: EditView(event: self.event))
        {
            Image(systemName: "pencil")
        }
    }
}

VStack 中,NavigationLink 的作用如预期般正常,并导航到编辑视图,但我想使用一个 contextMenu。尽管上下文菜单显示图像,但当我点击它时,它不会导航到编辑视图,而是仅取消上下文菜单。
我正在手表应用程序中执行此操作,但不认为这应该有任何区别,请问我是否需要在上下文菜单导航方面做任何特殊处理?

2
这个周末我花了很多时间来尝试让导航正常工作,但是我遇到了很多问题。我得出的结论是SwiftUI还远未完成,特别是在导航方面存在着奇怪的错误和副作用。 - meaning-matters
VStack 嵌入到 NavigationView 中是否有帮助? - meaning-matters
@meaning-matters - VStack并没有什么区别,我已经尝试了许多不同的方法,但都没有成功,这是最干净的呈现方式。谢谢你的建议。 - CodeChimp
1
我只能祝你好运! - meaning-matters
4个回答

4

在 Xcode 11.4 中,现在可以通过合理的 NavigationLink 按钮来实现这一点。耶!

.contextMenu {
    NavigationLink(destination: VisitEditView(visit: visit)) {
        Text("Edit visit")
        Image(systemName: "square.and.pencil")
    }
    NavigationLink(destination: SegmentsEditView(timelineItem: visit)) {
        Text("Edit individual segments")
        Image(systemName: "ellipsis")
    }
}

2
请您能详细说明一下吗?我在 Xcode 11.4 中使用它没有成功。 - protasm
我在那里发布的代码是从我的应用程序中粘贴复制的。所以那段代码对我来说是有效的。你尝试时会发生什么? - sobri
1
抱歉,我已经解决了。我没有在NavigationView中包装您的NavigationLinks,真是太傻了。谢谢! - protasm
这是你真正的代码吗?因为“EmptyView”作为目标并不会有什么可见性。你可能需要提供一个非空的目标视图。 - sobri
4
不好意思,无论目标是EmptyView()、TextView还是DestinationView(),结果都是一样的。如果显示contextMenu的对象也被包装在NavigationLink中,那么contextMenu项上的NavigationLink将无法导航到其目标。这与目标视图无关。 - protasm
显示剩余3条评论

4
我会使用isActive变量触发的NavigationLink变体,适用于动态/编程式导航。苹果在此文档中进行了说明 NavigationLink的这个变体非常适合动态/编程式导航。
您的.contextMenu将状态变量设置为true,从而激活NavigationLink。因为您不希望链接可见,所以将label视图设置为EmptyView 以下是一个示例,虽然与您的帖子不完全相同,但希望可以清楚地说明。
struct ContentView: View {

    @State private var showEditView = false

    var body: some View {

        NavigationView {
            VStack {
                Text("Long Press Me")
                    .contextMenu {
                        Button(action: {
                            self.showEditView = true
                        }, label: {
                            HStack {
                                Text("Edit")
                                Image(systemName: "pencil")
                            }
                        })
                }
                NavigationLink(destination: Text("Edit Mode View Here"), isActive: $showEditView) {
                    EmptyView()
                }
            }
            .navigationBarTitle("Context Menu")
        }
    }
}

我实现了这个功能,但无法显示 NavigationLink 的文本。我在 Button(action 中添加了一个 Print 语句,因此知道它已被触发,但仍然没有成功。 - CodeChimp
进一步的调查显示问题是EmptyView。如果我将其更改为NavigationLink(destination: EditView(event: self.event), isActive: $showEditView) {Text("Edit")},它可以工作,但显然上下文菜单的整个想法是我不想一直显示一个按钮。 - CodeChimp
你在视图层次结构中放置了NavigationLink吗?EmptyView()在我使用的每个示例中都有效,但也许它取决于它所处的位置? - KB-YYZ
我正在将它添加到VStack中,就像你的示例一样。另一个要注意的点是,在WatchOS上不支持NavigationView,因此VStack是我的视图中的顶级。 - CodeChimp
参考这个答案 https://dev59.com/G1MI5IYBdhLWcg3wA2ns#57321795,将其更改为文本标签并添加 .hidden() 就可以工作了!感谢您指出正确的方向。 - CodeChimp
1
太好了。我没有意识到 EmptyView 在 watchOS 上无法工作。关于 .hidden() 的技巧很不错。 - KB-YYZ

1

我发现在背景中遮盖NavigationLink并使用Button切换上下文是最简单的替代方案,也是最有效的。

struct ContentView: View {
    @State private var isShowing = false

    var body: some View {
        NavigationView {
            Text("Hello")
                .background(NavigationLink("", destination: Text("World!"), isActive: $isShowing))
                .contextMenu {
                    Button {
                        isShowing = true
                    } label: {
                        Label("Switch to New View", systemImage: "chevron.forward")
                    }
                }
        }
    }
}

1

这个在Xcode 11.6上可以工作。

struct ContentView: View {
    
    @State var isActiveFromContextMenu = false
    var body: some View {
        NavigationView{
            VStack{
                NavigationLink(destination : detailTwo(), isActive: $isActiveFromContextMenu ){
                    EmptyView()
                }
                
                List{
                    NavigationLink(destination: detail() ){
                        row(isActiveFromContextMenu: $isActiveFromContextMenu)
                    }
                    NavigationLink(destination: detail() ){
                        row(isActiveFromContextMenu: $isActiveFromContextMenu)
                    }
                    NavigationLink(destination: detail() ){
                        row(isActiveFromContextMenu: $isActiveFromContextMenu)
                    }
                }
            }       
        }   
    }    
}

struct detail: View {
    var body: some View{
        Text("Detail view")
    }
}

struct detailTwo: View {
    var body: some View{
        Text("DetailTwo view")
    }
}

struct row: View {
    
    @Binding var isActiveFromContextMenu : Bool
    var body: some View {
        
        HStack{
            
            Text("item")
            
        }.contextMenu{
            Button(action: {
                self.isActiveFromContextMenu = true
            })
            {
                Text("navigate to")
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接