How to add touch gesture to map but ignore touches on pins and annotations?

送分小仙女□ 提交于 2019-11-30 04:18:51

问题


I have a mapview that uses MKCircles to display radius information for certain user actions.

What I want to do, is allow the user to dismiss the MKCircle when they touch the map. However, I would like the MKCircle to NOT dismiss should the user touch any of the other pins or the MKCircle itself.

Any ideas?

Here is my current code, which dismisses the MKCircle when any part of the map is touched:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(deactivateAllRadars)];
[tap setCancelsTouchesInView:NO];
[_mapView addGestureRecognizer:tap];

回答1:


In the deactivateAllRadars method, you can use hitTest:withEvent: to tell whether an MKAnnotationView has been tapped or not.

An example of this is shown in How can I catch tap on MapView and then pass it to default gesture recognizers? (it's the second code sample).

This will let you avoid removing the circle if an annotation has been tapped.

If an annotation has not been tapped, you can then check if an MKCircle was tapped by getting the coordinates of the touch (see How to capture Tap gesture on MKMapView for an example) and seeing if the distance from the touch to the circle's center is greater than its radius.

Note that the deactivateAllRadars should be changed to deactivateAllRadars:(UITapGestureRecognizer *)tgr because it will need information from the associated gesture recognizer. Also be sure to add a colon at the end of the method's selector where you alloc+init tap.

For example:

-(void)deactivateAllRadars:(UITapGestureRecognizer *)tgr
{
    CGPoint p = [tgr locationInView:mapView];

    UIView *v = [mapView hitTest:p withEvent:nil];

    id<MKAnnotation> ann = nil;

    if ([v isKindOfClass:[MKAnnotationView class]])
    {
        //annotation view was tapped, select it...
        ann = ((MKAnnotationView *)v).annotation;
        [mapView selectAnnotation:ann animated:YES];
    }
    else
    {
        //annotation view was not tapped, deselect if some ann is selected...
        if (mapView.selectedAnnotations.count != 0)
        {
            ann = [mapView.selectedAnnotations objectAtIndex:0];
            [mapView deselectAnnotation:ann animated:YES];
        }


        //remove circle overlay if it was not tapped...        
        if (mapView.overlays.count > 0)
        {
            CGPoint touchPoint = [tgr locationInView:mapView];

            CLLocationCoordinate2D touchMapCoordinate 
              = [mapView convertPoint:touchPoint toCoordinateFromView:mapView];

            CLLocation *touchLocation = [[CLLocation alloc] 
              initWithLatitude:touchMapCoordinate.latitude 
              longitude:touchMapCoordinate.longitude];

            CLLocation *circleLocation = [[CLLocation alloc] 
              initWithLatitude:circleCenterLatitude 
              longitude:circleCenterLongitude];

            CLLocationDistance distFromCircleCenter 
              = [touchLocation distanceFromLocation:circleLocation];

            if (distFromCircleCenter > circleRadius)
            {
                //tap was outside the circle, call removeOverlay...
            }
        }
    }
}



回答2:


This is my Swift 2.1 compatible version:

func didTapOnMap(recognizer: UITapGestureRecognizer) {
    let tapLocation = recognizer.locationInView(self)
    if let subview = self.hitTest(tapLocation, withEvent: nil) {
        if subview.isKindOfClass(NSClassFromString("MKNewAnnotationContainerView")!) {
            print("Tapped out")
        }
    }
}

MKNewAnnotationContainerView is a private inner class, so you cannot compare directly like:

if subview is MKNewAnnotationContainerView {
}


来源:https://stackoverflow.com/questions/13498636/how-to-add-touch-gesture-to-map-but-ignore-touches-on-pins-and-annotations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!