【问题标题】:SwiftUI, selecting a row in a List programmaticallySwiftUI,以编程方式选择列表中的一行
【发布时间】:2020-09-02 09:46:43
【问题描述】:

我想以编程方式设置列表中的选定行。
在下面的示例中,通过 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

【问题讨论】:

    标签: list macos swiftui


    【解决方案1】:

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

    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 我测试了 Asperi 的答案。它工作正常。启动时选择为 2,但未在列表中显示为活动行。删除 .listStyle(SidebarListStyle()) 时,它确实有效。
    • 有没有办法在列表的可见区域滚动新选择的行?
    【解决方案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))
                }
    
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      它不会编译,因为标签不是唯一的。您正在设置标签 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 Asperi 是对的,选择必须声明为可选,如此处文档中所述developer.apple.com/documentation/swiftui/list
      • 代码编译时选择可选,但列表中的选择不可见,缺少什么?
      • @mica 所选项目是否更改?您的意思是未在列表中选择活动项目?
      • 有没有办法在列表的可见区域滚动新选择的行?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 2011-09-10
      • 1970-01-01
      相关资源
      最近更新 更多