2012-11-21 45 views
5

我有一個使用MKCircle s到顯示用於特定用戶操作半徑的信息的MapView類。如何添加觸摸手勢來映射但忽略引腳和註釋的觸摸?

我想要做的,是讓用戶關閉該MKCircle,當他們接觸到的地圖。不過,我希望MKCircle不要解僱,如果用戶觸摸任何其他引腳或MKCircle本身。

任何想法?

這裏是我當前的代碼,其中駁回時地圖的任何部分觸及MKCircle

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

回答

5

deactivateAllRadars方法,你可以使用hitTest:withEvent:告訴一個MKAnnotationView是否被竊聽或沒有。

此示例顯示在How can I catch tap on MapView and then pass it to default gesture recognizers?(這是第二個代碼示例)。

如果已經點擊註釋,則可以避免刪除該圓。

如果尚未點擊註釋,則可以通過獲取觸摸的座標(例如,參見How to capture Tap gesture on MKMapView)並檢查從觸摸到圓心的距離是否大於點擊來檢查MKCircle是否被點擊其半徑。

注意,deactivateAllRadars應改爲deactivateAllRadars:(UITapGestureRecognizer *)tgr,因爲它需要從相關的手勢識別信息。還要確保在方法的選擇器的末尾添加一個冒號,您需要在其中alloc + init tap

例如:

-(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... 
      } 
     } 
    } 
} 
+0

完美的作品! – JimmyJammed

+0

它不適用於iOS 7,在命中測試中返回MKNewAnnotationContainerView。任何想法如何解決它? –

+0

@RodrigoRuiz,MKNewAnnotationContainerView(私有類)是當你在地圖上面積這個特殊的代碼_doesn't護理about_挖掘什麼返回。當你點擊一個註解時,iOS 7仍然返回代碼_正在檢查for_的MKAnnotationView(記錄類)。如果還有問題,請詳細說明一個新問題。 – Anna

3

這是我雨燕2.1兼容版本:

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是一個私人的內部類,所以你不能直接比較,如:

if subview is MKNewAnnotationContainerView { 
} 
+0

對此我遲到了,但是當你說「私人內部類」時,這是否意味着這是一個私有類,它是另一個類(也許是MKAnnotationView)的內部? – Dallas

+0

你說得對,「內在」是誤導性的:我不知道MKNewAnnotationContainerView是在哪裏定義的,但它確實是私人的。如果您發現任何文檔,請隨時更新答案! –