如何在MKMapView上捕获Tap手势

31

我想捕捉在MKMapView上的轻触事件,以此可以在用户轻触的位置上放置一个MKPinAnnotation。基本上,我有一个覆盖在地图上的MKOverlayViews(显示建筑物的覆盖),当用户点击它时,我想通过放置MKPinAnnotaion并在弹出窗口中显示更多信息来为用户提供有关该覆盖的更多信息。

4个回答

59

您可以使用 UIGestureRecognizer 来检测地图视图上的触摸。

但是,我建议寻找双击 (UITapGestureRecognizer) 或长按 (UILongPressGestureRecognizer),而不是单击。单击可能会干扰用户尝试单击标记或弹出窗口本身。

在设置地图视图的位置(例如,在 viewDidLoad 中),将手势识别器附加到地图视图上:

UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] 
    initWithTarget:self action:@selector(handleGesture:)];
tgr.numberOfTapsRequired = 2;
tgr.numberOfTouchesRequired = 1;
[mapView addGestureRecognizer:tgr];
[tgr release];

或者长按使用:

UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] 
    initWithTarget:self action:@selector(handleGesture:)];
lpgr.minimumPressDuration = 2.0;  //user must press for 2 seconds
[mapView addGestureRecognizer:lpgr];
[lpgr release];

handleGesture: 方法中:
- (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];
}

谢谢您的建议,一旦我让它正常工作,我会尽快回复。我确实尝试了单击,但之后我无法显示我的PinAnnotations的标注。看起来我需要使用LongPressureGesture。 - sbkb
4
在iOS 6中,UITapGestureRecognizer不再能够在MKMapView上进行识别,而在iOS 5中则可以。对于这个问题有什么想法吗? - Felix
6
尝试实现shouldRecognizeSimultaneouslyWithGestureRecognizer,并在那里返回YES。在添加手势识别器之前,需要执行tgr.delegate = self;,以便调用该shouldRecognize委托方法。 - user467105
对于“Legal”链接有什么想法吗(不确定在提问时是否存在)?我希望它能像正常链接一样工作,并且我想要比迭代地图视图的子视图更聪明的方法来查看触摸是否在标签内部或其他位置。 - dokkaebi
还需要添加UIPanGestureRecognizer来处理缩放(pinch)和移动(pan)。 - Yasmin Tiomkin

5

我在viewDidLoad:中设置了一个长按(UILongPressGestureRecognizer),但它只能检测到第一个触摸。

我应该在哪里设置长按才能检测到所有的触摸?(这意味着地图准备好随时等待用户触摸屏幕来放置一个标记)

应该在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];
}

以下是与 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]);
    }   
}

2
如果您想在地图视图中使用单击/轻触,这是我正在使用的代码片段。(Cocoa和Swift)
let gr = NSClickGestureRecognizer(target: self, action: "createPoint:")
gr.numberOfClicksRequired = 1
gr.delaysPrimaryMouseButtonEvents = false // allows +/- button press
gr.delegate = self
map.addGestureRecognizer(gr)

在手势委托方法中,对双击手势进行了简单的测试...
func gestureRecognizer(gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: NSGestureRecognizer) -> Bool {
  let other = otherGestureRecognizer as? NSClickGestureRecognizer
  if (other?.numberOfClicksRequired > 1) {
    return true; // allows double click
  }

  return false
}

如果您想要将地图置于各种“状态”之一并允许单击/点击手势,则还可以在其他委托方法中过滤手势。


0
由于某些原因,UIGestureRecognizer在Swift中对我不起作用。当我使用UIGestureRecognizer时,使用touchesEnded方法返回MKNewAnnotationContainerView。似乎这个MKNewAnnotationContainerView阻塞了我的MKMapView。幸运的是,它是MKMapView的子视图。所以我循环遍历MKNewAnnotationContainerView的父视图直到self.view来获取MKMapView。最终我成功通过点击将地图固定。 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)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接