Как зафиксировать жест касания в MKMapView

Я пытаюсь зафиксировать событие нажатия на моем MKMapView, таким образом я могу поместить MKPinAnnotation в точку, где пользователь нажал. По сути, у меня есть карта с наложением MKOverlayViews (наложение, показывающее здание), и я хотел бы предоставить пользователю больше информации об этом наложении, когда они нажимают на него, опуская MKPinAnnotaion и показывая дополнительную информацию в выноске. Спасибо.


person sbkb    schedule 30.11.2010    source источник


Ответы (4)


Вы можете использовать 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];
}
person Community    schedule 30.11.2010
comment
Спасибо за совет, как только у меня все получится, я отвечу в ближайшее время. Я попробовал однократное нажатие, но после этого я не смог показать выноски своих PinAnnotations. Похоже, мне нужно использовать LongPressureGesture - person sbkb; 02.12.2010
comment
UITapGestureRecognizer больше не распознает MKMapView в iOS 6. Он работал в iOS 5. Есть идеи по этой проблеме? - person Felix; 10.10.2012
comment
@ phix23, попробуйте реализовать shouldRecognizeSimultaneouslyWithGestureRecognizer и вернуть оттуда YES. Потребуется выполнить tgr.delegate = self; перед добавлением GR для вызова этого метода делегата shoudRecognize. - person ; 10.10.2012
comment
Есть какие-нибудь мысли о юридической ссылке (не уверен, что она вообще существовала в то время, когда был задан этот вопрос)? Я хотел бы, чтобы это вело себя как обычно, и я хотел бы что-то более умное, чем итерация подвидов представления карты, чтобы увидеть, было ли касание внутри метки или чего-то еще. - person dokkaebi; 05.11.2013
comment
добавьте также UIPanGestureRecognizer для управления масштабированием (щипком) и перемещением (панорамирование) - person Yasmin Tiomkin; 14.08.2014

Я установил долгое нажатие (UILongPressGestureRecognizer) в viewDidLoad:, но он просто обнаруживает только одно касание с первого раза.

Где я могу настроить длительное нажатие для обнаружения всех касаний? (это означает, что карта готова каждый раз, когда пользователь ожидает прикосновения к экрану, чтобы нажать булавку)

Метод 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]);
    }   
}
person o0oKodako0o    schedule 23.03.2012

Если вы хотите использовать один щелчок/касание в представлении карты, вот фрагмент кода, который я использую. (Какао и Свифт)

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
}

вы также можете отфильтровать жест в других методах делегата, если хотите, чтобы Карта находилась в различных «состояниях», одно из которых допускало одно касание/щелчок

person bshirley    schedule 06.01.2016

По какой-то причине UIGestureRecognizer просто не работал у меня в Swift. Когда я использую способ UIGestureRecognizer. Когда я использовал метод touchesEnded, он возвращает MKNewAnnotationContainerView. Кажется, этот MKNewAnnotationContainerView заблокировал мой MKMapView. К счастью, это подвид MKMapView. Поэтому я перебрал суперпредставления MKNewAnnotationContainerView до self.view, чтобы получить MKMapView. И мне удалось закрепить mapView, нажав.

Свифт 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)
}
person William Tong    schedule 26.08.2018