Tap Action not working when Color is clear SwiftUI

Viewed 6689

my tapAction is not recognizing a tap when my foregroundColor is clear. When i remove the color it works fine.

That's my code:

ZStack {
    RoundedRectangle(cornerRadius: 0)
        .foregroundColor(Color.clear)
        .frame(width: showMenu ? UIScreen.main.bounds.width : 0)
        .tapAction {
            self.showMenu.toggle()
        }
    
    RoundedRectangle(cornerRadius: 5)
        .foregroundColor(Color.green)
        .shadow(radius: 5, y: 2)
        .padding(.trailing, 50)
        .frame(width: showMenu ? UIScreen.main.bounds.width : 0)
}
.edgesIgnoringSafeArea(.top)
3 Answers

I have also discovered that a shape filled with Color.clear does not generate a tappable area.

Here are two workarounds:

  1. Use Color.black.opacity(0.0001) (even on 10-bits-per-channel displays). This generates a color that is so transparent that it should have no effect on your appearance, and generates a tappable area that fills its frame. I don't know if SwiftUI is smart enough to skip rendering the color, so I don't know if it has any performance impact.

  2. Use a GeometryReader to get the frame size, and then use the contentShape to generate the tappable area:

    GeometryReader { proxy in
        Color.clear.contentShape(Path(CGRect(origin: .zero, size: proxy.size)))
    }
    

Here is the component

struct InvisibleButton: View {

    let action: (() -> Void)?

    var body: some View {
        Color.clear
        .contentShape(Rectangle())
        .onTapGesture {
            action?()
        }
    }
}

usage: Put your view and InbisibleButton in ZStack

ZStack {
     **yourView()**
     InvisibleButton {
        print("Invisible button tapped")
     }
}

you also can make a modifier to simplify usage:

struct InvisibleButtonModifier: ViewModifier {

    let action: (() -> Void)?

    func body(content: Content) -> some View {
        ZStack {
            content
            InvisibleButton(action: action)
        }

    }
}


     **yourView()**
     .modifier(InvisibleButtonModifier {
        print("Invisible button tapped")
      })

However, if your SwiftUI View has a UIKit view as a subview under, you will have to set Color.gray.opacity(0.0001) in order to UIView's touches be ignored

Related