【问题标题】:SwiftUI: Select NavigationLink in a NavigationView / List with SidebarListStyleSwiftUI:在带有 SidebarListStyle 的 NavigationView / List 中选择 NavigationLink
【发布时间】:2023-04-07 17:05:01
【问题描述】:

我想以编程方式在 NavigationView / List 中选择特定的 NavigationLink

以下代码在 iPhone 上无论是纵向还是横向模式都可以正常工作 == 在列表除了其目标视图之外不是永久可见的情况下。

代码:

struct ContentView: View {

private let listItems = [ListItem(), ListItem(), ListItem()]
@State var selection: Int? = 0

var body: some View {
    NavigationView {
        
        List(listItems.indices) {
            index in
            
            let item = listItems[index]
            let isSelected = (selection ?? -1) == index
            
            NavigationLink(destination: Text("Destination \(index)"),
                           tag: index,
                           selection: $selection) {
                
                Text("\(item.name) \(index) \(isSelected ? "selected" : "")")
                
            }
            
        }
    
    }
    .listStyle(SidebarListStyle())
    .onAppear(perform: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
            selection = 2
        })
    })
    }

}


struct ListItem: Identifiable {
    var id = UUID()
    var name: String = "Some Item"
}

但它在 iPad 上以横向模式失败:虽然导航本身可以正常工作(目的地显示正确),但 NavigationLink 仍未选中。

→ 如何选择 NavigationLink,使其在 iPad 上也显示为选中状态?

【问题讨论】:

    标签: swiftui navigationview navigationlink sidebarliststyle


    【解决方案1】:

    这是可能的方法。这个想法是通过视图模型以编程方式激活导航链接,但将模型级选择和表示(由链接拥有)选择分开。

    使用 Xcode 12b3 / iOS+iPadOS 14 测试。

    class SelectionViewModel: ObservableObject {
        var currentRow: Int = -1 {
            didSet {
                self.selection = currentRow
            }
        }
    
        @Published var selection: Int? = nil
    }
    
    struct SidebarContentView: View {
    @StateObject var vm = SelectionViewModel()
    private let listItems = [ListItem(), ListItem(), ListItem()]
    
    var body: some View {
        NavigationView {
    
            List(listItems.indices) {
                index in
    
                let item = listItems[index]
                let isSelected = vm.currentRow == index
    
                Button("\(item.name) \(index) \(isSelected ? "selected" : "")") { vm.currentRow = index }
                .background (
                    NavigationLink(destination: Text("Destination \(index) selected: \(vm.currentRow)"),
                                   tag: index,
                                   selection: $vm.selection) {
                        EmptyView()
                    }.hidden()
                )
            }
    
        }
        .listStyle(SidebarListStyle())
        .onAppear(perform: {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
                vm.currentRow = 2
            })
        })
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-08
      • 1970-01-01
      • 2020-05-22
      相关资源
      最近更新 更多