SwiftUI onTapGesture on Color.clear background behaves differently to Color.blue

It appears to be a design decision that any Color with an opacity of 0 is untappable.

Color.clear.onTapGesture { print("tapped") }                 // will not print
Color.blue.opacity(0).onTapGesture { print("tapped") }       // will not print
Color.blue.onTapGesture { print("tapped") }                  // will print
Color.blue.opacity(0.0001).onTapGesture { print("tapped") }  // will print

You can use the 4th option to get around this, as it is visually indistinguishable from the 1st.


The one line answer is instead of setting backgroundColor, please set contentShape for hit testing.

 var body: some View {
    GeometryReader { proxy in
        self.content()
            .fixedSize(horizontal: true, vertical: true)
            .frame(minWidth: proxy.size.width, minHeight: proxy.size.height)
            // ##################################################################
            // CHANGE COLOR HERE TO BLUE TO MAKE IT WORK
            // ##################################################################
            .contentShape(Rectangle())
            // ##################################################################
            .border(Color.yellow, width: 5)

    }
}

Transparent views are not tappable by default in SwiftUI because their content shape is zero.

You can change this behavior by using .contentShape modifier:

Color.clear
  .frame(width: 300, height: 300)
  .contentShape(Rectangle())
  .onTapGesture { print("tapped") } 

Tags:

Swiftui