如何修复 ForEach 循环中不可点击的按钮?

Posted

技术标签:

【中文标题】如何修复 ForEach 循环中不可点击的按钮?【英文标题】:How do I fix buttons not being tappable in a ForEach loop? 【发布时间】:2021-03-29 04:23:04 【问题描述】:

我有一个包含按钮的视图。带有按钮的视图是从 forEach 循环创建的。出于某种原因,只有一些按钮可以点击,而其他按钮则不能。

父视图包含一个 NavigationView,NavigationView 中的滚动视图,滚动视图中的lazyVStack,lazyVStack 中的 forEachloop 以及包含按钮的子视图。

struct ContentView: View 

  let peoples:[Person] = Bundle.main.decode("data.json")

  var body: some View 
    let columns = [
      GridItem(.flexible(minimum: 300), spacing: 10)
    ]

    NavigationView 
      ScrollView(.vertical) 
        LazyVStack 
          ForEach(peoples, id: \.self)  person in
            PersonView(name: person.Name, age: person.Age)
          
        
        .navigationTitle("A list of people")
        .navigationViewStyle(DefaultNavigationViewStyle())
        .padding()
      
    
  

子视图如下所示。我怀疑滚动视图正在窃取用户输入,但我不确定为什么或如何克服它。有些按钮是可粘贴的,有些则不是。

struct PersonView: View 

  @Environment(\.colorScheme) var colorScheme

  var name: String
  var age: Int

  var body: some View 
    VStack(alignment:.leading) 
      Image("randoPerson")
        .resizable()
        .scaledToFill()
        .frame(minWidth: nil, idealWidth: nil,
               maxWidth: UIScreen.main.bounds.width, minHeight: nil,
               idealHeight: nil, maxHeight: 300, alignment: .center)
        .clipped()
      VStack(alignment: .leading, spacing: 6) 
        Text("name")
          .fontWeight(.heavy)
          .padding(.leading)

        Text("Age \(age)")
          .foregroundColor(Color.gray)
          .padding([.leading,.bottom])


        Button(action:  print("I was tapped") ) 
          HStack 
            Image(systemName: "message.fill")
              .font(.title)
              .foregroundColor(.white)
              .padding(.leading)

            Text("Message them")
              .font(.subheadline)
              .foregroundColor(.white)
              .padding()
          
          .background(Color.blue)
        
        .padding()
      
      .background(Color(UIColor.systemBackground).cornerRadius(15))
      .shadow(color:colorScheme == .dark
                ? Color.white.opacity(0.2)
                : Color.black.opacity(0.2),
              radius: 7, x: 0, y: 2)
    
  

【问题讨论】:

【参考方案1】:

要解决此问题,您可以添加与 Person 关联的 id: UUID,并在 Person 之间使用其 ID 在 ForEach 内进行迭代。

您还会注意到我将值添加为小写以遵守 Swift 约定。

struct Person 

  let id: UUID // Add this value
  var name: String
  var age: Int

所以这里是用 id 替换 \.self 的 ContentView:

struct ContentView: View 

  let peoples: [Person] = Bundle.main.decode("data.json")

  var body: some View 
    NavigationView 
      ScrollView(.vertical) 
        LazyVStack 
          ForEach(peoples, id: \.id)  person in  // id replace \.self here
            PersonView(name: person.name, age: person.age)  // removed uppercase
          
        
        .navigationTitle("A list of people")
        .navigationViewStyle(DefaultNavigationViewStyle())
        .padding()
      
    
  

【讨论】:

以上是关于如何修复 ForEach 循环中不可点击的按钮?的主要内容,如果未能解决你的问题,请参考以下文章

[我想使用foreach循环php中的ajax来获取被点击行的UID,但获取所有UID

jsp页面中如何实现<c:forEach>循环一次就调用一次js函数?

单击时从循环中禁用按钮

如何批量删除list循环出来的值?

使用单选按钮使用Foreach循环禁用下拉菜单

Swiftui 如何在 foreach 循环中对整行使用 Tap Gesture