15

i'm try to pick some value from a swiftUI list with the ontapGesture.

I have a Searchlist of item, the user need to choose one item and then the app will send the choice to an array that later will be use for other info.

now my problem is how do I do that? how can do it? as you can see from the code below, I want to pick the value of the item.icaoAirport corresponding to that raw and pass to an array.

 List(dm.vettoreAeroporti.filter{
                //                    $0.icaoCode.contains(searchTerm)
                $0.icaoAirport.localizedCaseInsensitiveContains(searchTerm)
            }) { item in
                HStack {
                    Text(item.icaoAirport).bold()
                    Spacer()
                    Text(item.nameAirport)

                }
            }
            .onAppear {
                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    self.dm.openFileJson(fileName: "data")
                }
            }
            .onTapGesture {
                // ?? I need to take the value of the item.icaoAirport corresponding to that raw

            }

thanks in advance for the help.

Damiano Miazzi
  • 1,514
  • 1
  • 16
  • 38

4 Answers4

27

While your, Damiano, answer is right it works only on tap on the Text. Sometimes it is needed to have the whole row tappable, so here is the solution for this case:

List(items) { item in
    HStack {
        Text(item.icaoAirport).bold()
        Spacer()
        Text(item.nameAirport)
    }
    .contentShape(Rectangle())
    .onTapGesture {
        print("touched item \(item)")
    }
}

Thanks Paul for this (https://www.hackingwithswift.com/quick-start/swiftui/how-to-control-the-tappable-area-of-a-view-using-contentshape)

Note, that if you have content only on one side of the HStack e.g:

HStack {
    Text("Some text") // This text will be on the left side
}

then the .contentShape(Rectange()) will work only for the width of the text. So to enable it for the whole width just add a trailing Spacer() like this:

HStack {
    Text("Some text")
    Spacer() // This will take all the space from the end of the text up to the end of the whole row
}
.contentShape(Rectangle())
onmyway133
  • 45,645
  • 31
  • 257
  • 263
ramzesenok
  • 5,469
  • 4
  • 30
  • 41
2

I solved my issue:

HStack {
    Text(item.icaoAirport).bold()
    Spacer()
    Text(item.nameAirport)
        .onTapGesture {
            print("touched item \(item.icaoAirport)")        
        }
}
ramzesenok
  • 5,469
  • 4
  • 30
  • 41
Damiano Miazzi
  • 1,514
  • 1
  • 16
  • 38
  • 2
    this solution is not good. The text will be tappable but not the cell where the text is, what is not good. – Duck Oct 06 '20 at 22:22
2
List {
        ForEach(Type.allCases, id: \.self) { type in
                FilterRow(Color: type.Color,
                          title: type.Title)
                            .contentShape(Rectangle())
                            .onTapGesture {
                                print("Ammu type:\(type)")

                            }
                        
                    }
                }
Wasim
  • 921
  • 12
  • 14
2

This one is quite old but the accepted answers are pretty strange. I was able to achieve this effect in a much simpler way. Consider:

List {
  ForEach(myItems) { item in
    Button {
      // action
    } label: {
      Text(item.name)
    }
  }
}

Now doing it this way, the button is edge-to-edge in the row. However, the button is now the accent color of your app. That's probably not what you want! So I tried adding:

Button(...)
  .buttonStyle(PlainButtonStyle())

The text of the button is now the primary foreground color, great! But there's a different problem now! The button no longer goes edge-to-edge, it's only the text. To fix this, i instead:

Button(...)
  .foregroundColor(.primary)

This is edge-to-edge with primary color text and custom actions. No need to create HStacks with spacers and an onTap, it's all just handled. OP's post has text on both sides so likely still needs an HStack for their specific usecase but a Button is still probably a better choice.

Procrastin8
  • 4,193
  • 12
  • 25