最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ios - Detect touchgesture outside SwiftUI view without handling it - Stack Overflow

programmeradmin5浏览0评论

I use a ZStack to show a info box above the screen content. When tapping outside the box, it should be dismissed and the tap should still be handled by the screen content.

Basically I am looking for a onTouchOutside equivalent.

My first approach to handle the tap and to dismiss the box, was to add another full screen view below box (= between the box and the screen content) and using .onTapGesture on this view. While this works fine to dismiss the box, the tap is consumed and thus not used by the underlying screen content.

I found several older articles about similar problems, saying that this is not possible. However, being several years old, I wonder if this is still the case. Does SwiftUI really lack such a basic and important feature?

A custom TouchPassthroughView does not work as well. The touch is also consumed.

Are any solutions 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(target: context.coordinator, action: #selector(Coordinator.handleTap(_:)))
        tapGesture.cancelsTouchesInView = false
        view.addGestureRecognizer(tapGesture)

        return view
    }

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

struct InfoView: View {
    @State private var showBox = true
    
    var body: some View {
        ZStack {
            VStack {
                Text("Screen Content")
                    .padding()
                    .background(Color.blue)
                    .onTapGesture {
                        print("Background tapped")
                    }
            }

            if showBox {
                TouchPassthroughView {
                    print("Tap outside")
                    showBox = false
                }
                .ignoresSafeArea()

                VStack {
                    Text("Box")
                        .padding()
                        .background(Color.white)
                        .cornerRadius(12)
                }
                .frame(width: 200, height: 150)
                .padding(.top, 100)
                .shadow(radius: 10)
            }
        }
    }
} 
发布评论

评论列表(0)

  1. 暂无评论