SwiftUI - 使工具栏的 NavigationLink 使用详细视图

SwiftUI - Make toolbar's NavigationLink use detail view

我正在开发一个双面板 SwiftUI 应用程序,在 DoubleColumnNavigationView.

中带有侧边栏和详细信息面板

我想从侧边栏的工具栏打开一个 NavigationLink 到详细信息窗格,如下面 gif 中的“从侧边栏打开”所示。

但是,视图以堆栈的形式打开,如下面 gif 中的“从工具栏打开”所示。

使用 isDetailLink(true) 似乎没有效果。

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: Text("Opened from sidebar")) {
                    Text("Open from sidebar")
                }
            }.listStyle(SidebarListStyle())
            .navigationTitle("Sidebar")
            .toolbar {
                ToolbarItem {
                    // This should open in detail pane
                    NavigationLink(destination: Text("Opened from toolbar")) {
                        Text("Open from toolbar")
                    }
                }
            }
            Text("Detail pane")
        }.navigationViewStyle(DoubleColumnNavigationViewStyle())
    }
}

通用解决方案

如您所知,NavigationLink 放在 toolbar 中效果不佳。这里的建议是将 Button 放入 toolbar 并在代码中的某处使用隐藏的 NavigationLink。该按钮告诉 link 打开详细视图,然后 link 执行操作。这是根据此建议调整的代码:

struct ContentView: View {
    /// A state that tracks whether the link in the toolbar should be opened
    @State var toolbarLinkSelected = false
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: Text("Opened from sidebar")) {
                    Text("Open from sidebar")
                }
            }.listStyle(SidebarListStyle())
            .navigationTitle("Sidebar")
            .toolbar {
                ToolbarItem {
                    Button(action: { toolbarLinkSelected = true }) {
                        Text("Open from toolbar")
                    }
                }
            }
            .background(
                NavigationLink(
                    destination: Text("Opened from toolbar"),
                    isActive: $toolbarLinkSelected
                ) {
                    EmptyView()
                }.hidden() // The link is not visible to user
            )
            Text("Detail pane")
        }.navigationViewStyle(DoubleColumnNavigationViewStyle())
    }
}

iOS / iPadOS 唯一解决方案

另外,如果您只需要支持 iOS 和 iPadOS,您可以使用 navigationBarItems 来实现它。这在 macOS 上不起作用,因为此修饰符不可用,但适用于 iOS/iPadOS。这是示例:

struct ContentView: View {
    var body: some View {
        NavigationView {
            List {
                NavigationLink(destination: Text("Opened from sidebar")) {
                    Text("Open from sidebar")
                }
            }.listStyle(SidebarListStyle())
            .navigationTitle("Sidebar")
            .navigationBarItems(trailing: NavigationLink(destination: Text("Opened from toolbar")) {
                Text("Open from toolbar")
            })
            Text("Detail pane")
        }.navigationViewStyle(DoubleColumnNavigationViewStyle())
    }
}