Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect a tap gesture location in SwiftUI?

Tags:

swift

swiftui

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

struct ContentView : View {     @State var points:[CGPoint] = [CGPoint(x:0,y:0), CGPoint(x:50,y:50)]     var body: some View {         return ZStack {             Color.gray                 .tapAction {                    // TODO: add an entry to self.points of the location of the tap                 }             ForEach(self.points.identified(by: \.debugDescription)) {                 point in                 Color.red                     .frame(width:50, height:50, alignment: .center)                     .offset(CGSize(width: point.x, height: point.y))             }         }     } } 

I'm assuming instead of tapAction, I need to have a TapGesture or something? But even there I don't see any way to get information on the location of the tap. How would I go about this?

like image 625
Epaga Avatar asked Jun 09 '19 10:06

Epaga


People also ask

How do I get tap location in SwiftUI?

Starting from iOS 16 and macOS 13, we can get the location of a tap in SwiftUI. The new onTapGesture(count:coordinateSpace:perform:) overload of onTapGesture() modifier provides the location in its perform closure and allows us to request the location in local or global coordinate space.

What is tap gesture?

The Tap gesture detects a deliberate tap on a component, in a manner that is more restrictive than onPress . Tap imposes the following additional restrictions with respect to the initial down and final pointer up events: They must occur within a short distance, to rule out drag-like gestures.

What is UITapGestureRecognizer Swift?

UITapGestureRecognizer is a concrete subclass of UIGestureRecognizer . For gesture recognition, the specified number of fingers must tap the view a specified number of times. Although taps are discrete gestures, they're discrete for each state of the gesture recognizer.

How do I add gestures in Swift?

Adding a Tap Gesture Recognizer to an Image View in Interface Builder. Open Main. storyboard and drag a tap gesture recognizer from the Object Library and drop it onto the image view we added earlier. The tap gesture recognizer appears in the Document Outline on the left.


1 Answers

Well, after some tinkering around and thanks to this answer to a different question of mine, I've figured out a way to do it using a UIViewRepresentable (but by all means, let me know if there's an easier way!) This code works for me!

struct ContentView : View {     @State var points:[CGPoint] = [CGPoint(x:0,y:0), CGPoint(x:50,y:50)]     var body: some View {         return ZStack(alignment: .topLeading) {             Background {                    // tappedCallback                    location in                     self.points.append(location)                 }                 .background(Color.white)             ForEach(self.points.identified(by: \.debugDescription)) {                 point in                 Color.red                     .frame(width:50, height:50, alignment: .center)                     .offset(CGSize(width: point.x, height: point.y))             }         }     } }  struct Background:UIViewRepresentable {     var tappedCallback: ((CGPoint) -> Void)      func makeUIView(context: UIViewRepresentableContext<Background>) -> 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 tappedCallback: ((CGPoint) -> Void)         init(tappedCallback: @escaping ((CGPoint) -> Void)) {             self.tappedCallback = tappedCallback         }         @objc func tapped(gesture:UITapGestureRecognizer) {             let point = gesture.location(in: gesture.view)             self.tappedCallback(point)         }     }      func makeCoordinator() -> Background.Coordinator {         return Coordinator(tappedCallback:self.tappedCallback)     }      func updateUIView(_ uiView: UIView,                        context: UIViewRepresentableContext<Background>) {     }  } 
like image 177
Epaga Avatar answered Sep 30 '22 19:09

Epaga