Better way of handling Tap Gesture on Lists

Viewed 31

I'm trying to implement a 1 count tap gesture and 2 count tap gesture on rows of a list view.

Currently I'm achieving this by expanding the contents of the rows to fill the entire width and height, by changing the row insets with .listRowInsets(EdgeInsets()) and adding an HStack with a Spacer inside. As seen below:

My ListRow View, which serves to attempt to fill out the the entire rows' width and height. (With a red border for debugging):

struct ListRow<Content: View> : View {
    let content: () -> Content

    var body: some View {
        HStack {
            content()
            Spacer()
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .contentShape(Rectangle())
        .border(Color.red)
    }
}

And here's a snippet of one of the two places I'm using a list with my ListRow:

List(selection: $selectedItem) {
    Section(header: Text("Favourites")) {
        ForEach($sidebarItems, id: \.self) { $item in
            ListRow {
                FileLabel(URL(string: item.path)!, size: 14, text: item.text)
            }.gesture(TapGesture().onEnded {
                selectedItem = item
                fileState.updatePath(path: item.path)
            }).listRowInsets(EdgeInsets())
        }
    }
}.listStyle(SidebarListStyle())

A few issues happen here, which both feels hacky and incorrect to do.

  1. I have to manually select the row when the content is tapped.
  2. I actually manually have to focus the list, if it's not actually focused when clicking a row, otherwise the selection is a very faint color.
  3. The contents aren't actually expanding to the leading and trailing edges of the row, no matter if I give my EdgeInsets negative values (This just results in the contents getting clipped, rather than expanding to the edge).
  4. Clicking the areas outside of the red border (seen below) results in the row being selected, but the tap action not firing.

Image showing the issues described above

Preferably I'd love if there was a way to listen for tap gestures on a list and get the row that was tapped. It would fix having to manually reimplement features that the List already has built-in and lowering the risk of introducing bugs + it just feels like the right way to do it, unfortunately I haven't been able to find other ways of implementing this, other than creating an HStack with a Spacer.

0 Answers
Related