Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't SwiftUI onTapGesture always work

The onTapGesture in SWiftUI doesn't work reliably. This example shows the problem, which is that sometimes when you tap on a cell, the background changes to grey as it should, and another time an adjacent cell changes and at other time nothing happens at all. Any ideas why?

struct ContentView: View {
    @State var cellFg: [[Color]] = [
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear],
        [.clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear, .clear]
    ]
    
    var body: some View {
        VStack {
            Spacer()
            ForEach(0..<9) { row in
                HStack {
                    Spacer()
                    ForEach(0..<9) { column in
                        Rectangle()
                            .foregroundColor(cellFg[row][column])
                            .border(Color.gray, width: 1)

                            // When you tap, it sometimes works, sometimes selects
                            // an adjacent cell and sometimes does nothing
                            .onTapGesture {
                                print("Row \(row) - Column\(column)")
                                cellFg[row][column] = .gray
                            }
                    }
                    Spacer()
                }
            }
            Spacer()
        }
    }
}
like image 835
Jmcg Avatar asked Jul 29 '20 13:07

Jmcg


1 Answers

Rectangle here is transparent but gesture requires content to be opaque.

Here is a fix (tested with Xcode 11.4 / iOS 13.4)

Rectangle()
    .foregroundColor(self.cellFg[row][column])
    .border(Color.gray, width: 1)
    .contentShape(Rectangle())         // << here !!

the .contentShape make hit-testable entire frame independently of transparency.

like image 107
Asperi Avatar answered Nov 20 '22 03:11

Asperi