ios4 - Cómo capturar el gesto de tap en MKMapView
uitapgesturerecognizer mkoverlay (4)
Estoy tratando de capturar el evento tap en mi MKMapView
, de esta manera puedo soltar un MKPinAnnotation
en el punto donde el usuario tocó. Básicamente, tengo un mapa MKOverlayViews
con MKOverlayViews
(una superposición que muestra un edificio) y me gustaría dar más información al usuario sobre esa Superposición cuando la tocan al soltar un MKPinAnnotaion
y mostrar más información en la llamada. Gracias.
Configuré una pulsación larga ( UILongPressGestureRecognizer
) en viewDidLoad:
pero solo detecta el único toque desde el primero.
¿Dónde puedo configurar una pulsación larga para detectar todo el tacto? (significa que el mapa está listo cada vez que se espera que el usuario toque la pantalla para presionar un alfiler)
El método viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];mapView.mapType = MKMapTypeStandard;
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
[self.mapView addGestureRecognizer:longPressGesture];
[longPressGesture release];
mapAnnotations = [[NSMutableArray alloc] init];
MyLocation *location = [[MyLocation alloc] init];
[mapAnnotations addObject:location];
[self gotoLocation];
[self.mapView addAnnotations:self.mapAnnotations];
}
y el método handleLongPressGesture
:
-(void)handleLongPressGesture:(UIGestureRecognizer*)sender {
// This is important if you only want to receive one tap and hold event
if (sender.state == UIGestureRecognizerStateEnded)
{NSLog(@"Released!");
[self.mapView removeGestureRecognizer:sender];
}
else
{
// Here we get the CGPoint for the touch and convert it to latitude and longitude coordinates to display on the map
CGPoint point = [sender locationInView:self.mapView];
CLLocationCoordinate2D locCoord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
// Then all you have to do is create the annotation and add it to the map
MyLocation *dropPin = [[MyLocation alloc] init];
dropPin.latitude = [NSNumber numberWithDouble:locCoord.latitude];
dropPin.longitude = [NSNumber numberWithDouble:locCoord.longitude];
// [self.mapView addAnnotation:dropPin];
[mapAnnotations addObject:dropPin];
[dropPin release];
NSLog(@"Hold!!");
NSLog(@"Count: %d", [mapAnnotations count]);
}
}
Por alguna razón, UIGestureRecognizer simplemente no funcionó para mí en Swift. Cuando uso el modo UIGestureRecognizer. Cuando utilicé el método touchesEnded, devuelve un MKNewAnnotationContainerView. Parece que este MKNewAnnotationContainerView bloqueó mi MKMapView. Afortunadamente, es una subvista de MKMapView. Así que hice un bucle a través de las vistas de supervisión de MKNewAnnotationContainerView hasta la autoevaluación para obtener el MKMapView. Y logré fijar el mapView tocando.
Swift 4.1
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
let t = touches.first
print(t?.location(in: self.view) as Any)
print(t?.view?.superview?.superview.self as Any)
print(mapView.self as Any)
var tempView = t?.view
while tempView != self.view {
if tempView != mapView {
tempView = tempView?.superview!
}else if tempView == mapView{
break
}
}
let convertedCoor = mapView.convert((t?.location(in: mapView))!, toCoordinateFrom: mapView)
let pin = MKPointAnnotation()
pin.coordinate = convertedCoor
mapView.addAnnotation(pin)
}
Puede usar un UIGestureRecognizer
para detectar toques en la vista del mapa.
Sin embargo, en lugar de un solo toque, sugeriría buscar un doble toque ( UITapGestureRecognizer
) o una pulsación larga ( UILongPressGestureRecognizer
). Un solo toque puede interferir con el usuario que intenta hacer un solo toque en el pin o la propia llamada.
En el lugar donde configura la vista de mapa (en viewDidLoad
por ejemplo), adjunte el reconocedor de gestos a la vista de mapa:
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleGesture:)];
tgr.numberOfTapsRequired = 2;
tgr.numberOfTouchesRequired = 1;
[mapView addGestureRecognizer:tgr];
[tgr release];
o para utilizar una pulsación larga:
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleGesture:)];
lpgr.minimumPressDuration = 2.0; //user must press for 2 seconds
[mapView addGestureRecognizer:lpgr];
[lpgr release];
En el handleGesture:
método:
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate =
[mapView convertPoint:touchPoint toCoordinateFromView:mapView];
MKPointAnnotation *pa = [[MKPointAnnotation alloc] init];
pa.coordinate = touchMapCoordinate;
pa.title = @"Hello";
[mapView addAnnotation:pa];
[pa release];
}
Si desea utilizar un solo clic / toque en la vista del mapa, aquí hay un fragmento de código que estoy usando. (Cocoa y Swift)
let gr = NSClickGestureRecognizer(target: self, action: "createPoint:")
gr.numberOfClicksRequired = 1
gr.delaysPrimaryMouseButtonEvents = false // allows +/- button press
gr.delegate = self
map.addGestureRecognizer(gr)
en el método de delegado de gestos, una prueba simple para preferir el gesto de doble toque ...
func gestureRecognizer(gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: NSGestureRecognizer) -> Bool {
let other = otherGestureRecognizer as? NSClickGestureRecognizer
if (other?.numberOfClicksRequired > 1) {
return true; // allows double click
}
return false
}
También puede filtrar el gesto en otros métodos de delegado si desea que el Mapa esté en varios "estados", uno de los cuales permitió el toque / clic único.