How to detect a tap gesture location in SwiftUI?

前端 未结 3 1589
小蘑菇
小蘑菇 2020-12-01 12:39

(For SwiftUI, not vanilla UIKit) Very simple example code to, say, display red boxes on a gray background:

struct ContentView : View {
    @State var points:         


        
3条回答
  •  佛祖请我去吃肉
    2020-12-01 13:22

    Just in case someone needs it, converted the above answer into a view modifier which also takes a CoordniateSpace as an optional parameter

    import SwiftUI
    import UIKit
    
    public extension View {
      func onTapWithLocation(coordinateSpace: CoordinateSpace = .local, _ tapHandler: @escaping (CGPoint) -> Void) -> some View {
        modifier(TapLocationViewModifier(tapHandler: tapHandler, coordinateSpace: coordinateSpace))
      }
    }
    
    fileprivate struct TapLocationViewModifier: ViewModifier {
      let tapHandler: (CGPoint) -> Void
      let coordinateSpace: CoordinateSpace
    
      func body(content: Content) -> some View {
        content.overlay(
          TapLocationBackground(tapHandler: tapHandler, coordinateSpace: coordinateSpace)
        )
      }
    }
    
    fileprivate struct TapLocationBackground: UIViewRepresentable {
      var tapHandler: (CGPoint) -> Void
      let coordinateSpace: CoordinateSpace
    
      func makeUIView(context: UIViewRepresentableContext) -> UIView {
        let v = UIView(frame: .zero)
        let gesture = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.tapped))
        v.addGestureRecognizer(gesture)
        return v
      }
    
      class Coordinator: NSObject {
        var tapHandler: (CGPoint) -> Void
        let coordinateSpace: CoordinateSpace
    
        init(handler: @escaping ((CGPoint) -> Void), coordinateSpace: CoordinateSpace) {
          self.tapHandler = handler
          self.coordinateSpace = coordinateSpace
        }
    
        @objc func tapped(gesture: UITapGestureRecognizer) {
          let point = coordinateSpace == .local
            ? gesture.location(in: gesture.view)
            : gesture.location(in: nil)
          tapHandler(point)
        }
      }
    
      func makeCoordinator() -> TapLocationBackground.Coordinator {
        Coordinator(handler: tapHandler, coordinateSpace: coordinateSpace)
      }
    
      func updateUIView(_: UIView, context _: UIViewRepresentableContext) {
        /* nothing */
      }
    }
    

提交回复
热议问题