10.8 C
New York
Wednesday, March 26, 2025

ios – Detect contact / gesture outdoors SwiftUI view with out dealing with it


I exploit a ZStack to point out a information field above the display content material. When tapping outdoors the field, it needs to be dismissed and the faucet ought to nonetheless be dealt with by the display content material.

Principally I’m on the lookout for a onTouchOutside equal.

My first strategy to deal with the faucet and to dismiss the field, was so as to add one other full display view under field (= between the field and the display content material) and utilizing .onTapGesture on this view. Whereas this works high quality to dismiss the field, the faucet is consumed and thus not utilized by the underlying display content material.

I discovered a number of older articles about related issues, saying that this isn’t doable. Nonetheless, being a number of years previous, I’m wondering if that is nonetheless the case. Does SwiftUI actually lack such a primary and essential function?

A customized TouchPassthroughView doesn’t work as effectively. The contact can be consumed.

Are any options for this?


struct TouchPassthroughView: UIViewRepresentable {
    var tappedOutside: () -> Void

    class Coordinator: NSObject {
        let tappedOutside: () -> Void

        init(tappedOutside: @escaping () -> Void) {
            self.tappedOutside = tappedOutside
        }

        @objc func handleTap(_ sender: UITapGestureRecognizer) {
            tappedOutside()
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(tappedOutside: tappedOutside)
    }

    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        view.backgroundColor = .clear

        let tapGesture = UITapGestureRecognizer(goal: context.coordinator, motion: #selector(Coordinator.handleTap(_:)))
        tapGesture.cancelsTouchesInView = false
        view.addGestureRecognizer(tapGesture)

        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {}
}

struct InfoView: View {
    @State non-public var showBox = true
    
    var physique: some View {
        ZStack {
            VStack {
                Textual content("Display screen Content material")
                    .padding()
                    .background(Colour.blue)
                    .onTapGesture {
                        print("Background tapped")
                    }
            }

            if showBox {
                TouchPassthroughView {
                    print("Faucet outdoors")
                    showBox = false
                }
                .ignoresSafeArea()

                VStack {
                    Textual content("Field")
                        .padding()
                        .background(Colour.white)
                        .cornerRadius(12)
                }
                .body(width: 200, peak: 150)
                .padding(.prime, 100)
                .shadow(radius: 10)
            }
        }
    }
} 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles