I have a UIImageView above a MapView.
I am currently able to draw lines on the UIImageView which is why i have TouchesBegan, TouchesMoved & TouchesEnded attached to it.
When i pinch however, i want the mapView which is underneath to zoom in and out and not the UIImageView. When i stop pinching i want to be able to draw on the UIImageView once again.
class ViewController: UIViewController, CLLocationManagerDelegate, GMSMapViewDelegate, UIGestureRecognizerDelegate {
@IBOutlet weak var myMapView: GMSMapView!
myMapView.delegate = self
lazy var canvasView: CanvasView = {
var overlayView = CanvasView(frame: CGRect(x:0, y: 0, width: self.myMapView.frame.width, height: self.myMapView.frame.height))
overlayView.isUserInteractionEnabled = true
overlayView.delegate = self
return overlayView
}()
class CanvasView: UIImageView {
var lastPoint = CGPoint.zero
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
//Do something...
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
}
}
}
}
I've tried to use a pinchGesture. The issue is that its always triggered after all other events. I cannot use it before a hittest or a touchesMoved is triggered. I also can't seem to be able to pass the pinch data from a UIImageView to a MapView to zoom in and out appropriately.
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
pinchGesture.delegate = self
overlayView.addGestureRecognizer(pinchGesture)
@objc func handlePinch(_ sender: UIPinchGestureRecognizer? = nil) {
//Do something
}
Since pinch gesture is triggered after a hittest i cant use it to determine which view to return in a hittest. Another way would be to determine how many fingers where used on screen. This does not work either however.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
var view = super.hitTest(point, with: event)
if Int(event?.allTouches?.count ?? 0) > 1 {
return nil
}
return view
}
I can however detect how many fingers where used in a touchedBegan so i've tried to intercept the touch once it starts without any progress.
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if Int(event?.allTouches?.count ?? 0) > 1 {
self.canvasView.isUserInteractionEnabled = false
}
}
How can this be achieved? I'm running out of ideas..
My approach for this case would be to actually subclass your map view and forward touch events to the view that you draw to.
Since your map view needs to recognise the gesture it should be the view that responds to initial events. And once the gesture is recognised you will get a call to notify you that touches have been canceled.
I used the following to prototype it:
Obviously this code needs improvements when it comes to handling touch events and drawing. I would suggest not to call touch events (e.g.
touchesBegan) onforwardsTouchEventsTobut rather create a protocol and use that to forward events through custom methods.But it should nicely show the working solution. The touch events get called until they are canceled by the gesture recogniser. Even more the view that is drawing can remove the path that is being drawn due to one finger being recognised before the gesture.