SwiftUI,以编程方式在列表中选择一行

时间:2020-05-16 14:28:50

标签: list macos swiftui

我想以编程方式设置列表中的选定行。
在下面的示例中,通过2个按钮。

struct ContentView: View {

  @State private var selection = 2

  var body: some View {
    VStack {
      List() {
      //List(selection: $selection)  {.  // does not compile
        Text("Line 0").tag(1)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
      }
      .listStyle(SidebarListStyle())
      Text("Selected Item :\(self.selection)")
      HStack {
        Button(action: {if (self.selection < 5 ) { self.selection += 1 }} ) {Text("⬇︎")}
        Button(action: {if (self.selection > 0 ) { self.selection -= 1 }} ) {Text("⬆︎")}
      }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

试图使列表像这样可选:

List(selection: $selection)  

无法编译。
编译器抱怨:Unable to infer complex closure return type; add explicit type to disambiguate

3 个答案:

答案 0 :(得分:3)

选择类型必须是可选的。查找下面的固定代码。

struct TestListSelectionOnAction: View {

  @State private var selection: Int? = 2 // optional !!

  var body: some View {
    VStack {
      List(selection: $selection)  {
        Text("Line 0").tag(0)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
      }
      .listStyle(SidebarListStyle())
      Text("Selected Item :\(self.selection ?? -1)")
      HStack {
        Button(action: {
            if (self.selection! < 5 ) { self.selection! += 1 }} ) {Text("⬇︎")}
        Button(action: {
            if (self.selection! > 0 ) { self.selection! -= 1 }} ) {Text("⬆︎")}
      }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
}

答案 1 :(得分:1)

由于标签不是唯一的,因此无法编译。您正在两次设置标签1。它无法识别值,这就是List(selection: $selection)也不起作用的原因。

 List() {
      //List(selection: $selection)  {.  // should compile now
        Text("Line 0").tag(0)
        Text("Line 1").tag(1)
        Text("Line 2").tag(2)
        Text("Line 3").tag(3)
        Text("Line 4").tag(4)
        Text("Line 5").tag(5)
 }

答案 2 :(得分:1)

感谢 Introspect:https://github.com/siteline/SwiftUI-Introspect

处理 iPad 侧边栏无法设置默认行并使所选样式在初始时可见:

示例:

struct TempData: Identifiable {
    var id: Int
    var title: String
}

struct TempView: View {
    // handle selection nil: when detail view pushs view, selection == nil
    @State private var keepSelection: Int = 2
    // bind list selected row
    @State private var selection: Int? = 2 // set default row

    private var dataArr: [TempData] = [TempData(id: 1, title: "one"),
                                   TempData(id: 2, title: "two"),
                                   TempData(id: 3, title: "three")]

    var body: some View {
        List(selection: $selection) {
            ForEach(dataArr.indices) { index in
                NavigationLink(destination: Text("\(dataArr[index].title)").onAppear {
                    keepSelection = (selection != nil ? selection! : keepSelection)
                }, tag: dataArr[index].id, selection: $selection) {
                    HStack {
                    Text("\(dataArr[index].title)")
                    }
                }
                .introspectTableViewCell(customize: { cell in
                    // import Introspect
                    // https://github.com/siteline/SwiftUI-Introspect
                    cell.selectionStyle = .none
                    cell.backgroundColor = .systemGroupedBackground
                })
                .tag(dataArr[index].id) // or use enum
                .listRowBackground(keepSelection == dataArr[index].id ? Color.accentColor.cornerRadius(10.0): Color(UIColor.systemGroupedBackground).cornerRadius(10))
            }

        }
    }
}