SwiftUI,如何在程序中编程选择列表中的一行

6
我希望能够通过编程方式设置列表中的选定行。
以下是我的示例,通过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)  

代码无法编译。


编译器报错: 无法推断复杂闭包的返回类型; 添加显式类型以消除歧义

3个回答

5

选择类型必须是可选的。以下是已修复的代码。

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)
  }
}

代码现在可以编译了,但是列表中的选择不可见,缺少什么? - mica
1
@mica 我测试了Asperi的答案,它可以正常工作。当启动选择为2时,在列表中并没有显示为活动行。但是,如果删除.listStyle(SidebarListStyle()),它就可以正常工作。 - davidev
1
有没有办法将新选择的行滚动到列表的可见区域内? - mica

2
感谢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))
            }

        }
    }
}

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)
 }

在使用唯一标签进行更正后,编译器错误仍然存在。 - mica
1
@mica Asperi是正确的,选择必须声明为可选项,如此文档中所述 https://developer.apple.com/documentation/swiftui/list - davidev
代码使用可选项编译,但列表中的选择不可见,缺少什么? - mica
1
@mica 选定的项目是否发生了变化?你是指列表中的活动项目未被选中? - davidev
有没有办法将新选择的行滚动到列表的可见区域内? - mica

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