来自MKPolylineView的标注?

时间:2012-03-29 18:49:49

标签: ios mkmapview mkannotation mkoverlay

当有人触摸MKPolylineView时,有没有办法显示标注? 我试图添加一个UITapGestureRecognizer并在选择器中以某个坐标显示一个标注。但没有工作。有什么建议吗?

以下是我在方法

中尝试的内容
 - (MKOverlayView *)mapView:(MKMapView *)mapa viewForOverlay:(id <MKOverlay>)overlay
        self.polylineView = [[MKPolylineView alloc] initWithPolyline: self.polyline];
        self.polylineView.strokeColor = [UIColor blackColor];
        self.polylineView.lineWidth = 5.0;
        self.polylineView.alpha = 0.7;
        UITapGestureRecognizer *touchOnView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(addBubble:)];
        [touchOnView setNumberOfTapsRequired:1];
        [touchOnView setNumberOfTouchesRequired:1];
        [self.polylineView addGestureRecognizer:touchOnView];

1 个答案:

答案 0 :(得分:8)

非常有趣的问题 - 我从未想过将手势识别器放在地图叠加层上。通过一些实验,我已经验证可以检测MKPolylineView上的点按。就像您发现的那样,点击手势在地图叠加层上不起作用。因此,我将点击手势放在MKMapView而不是MKPolylineView上。然后处理水龙头:

- (void)handleTapGesture:(UIGestureRecognizer*)gestureRecognizer
{
    if (measureLine != nil)
    {
        UIView* hitView = [self.polylineView hitTest:[gestureRecognizer locationInView:self.polylineView] withEvent:nil];
    }
}
如果您的点按位于hitView之外,

MKPolylineView将为零,如果点击位于其中,则<{1}}将为self.polylineView

然而,这可能不会像你想的那样表现得很好。对于水平和垂直线,它完美地工作,因为底层视图的大小与线的大小大致相同。但是对于45度线,底层视图必须远大于线,因为它是一个轴对齐的边界框(AABB)。如果您考虑45度线,仅使用水平和垂直线将其封闭,您将得到一个较大的区域 - 比您想要检测的水龙头大得多。

e.g。

--------
|    / |
|   /  |
|  /   |
| /    |
|/     |
--------

但是使用点击手势或点击测试将始终导致识别这些AABB内的点击。所以无论你在哪里尝试附加你的手势 - 例如在您尝试的MKPolylineViewMKMapView时,您会得到虚假的结果。对于较长的线条,问题会变得更糟 - 如果您想象从地图视图的右上角到左下角的线条,您需要将其封闭的AABB将覆盖地图视图的整个区域,这意味着点击左上角或右下角将被解释为点击MKPolylineView

要解决这个问题,我建议采用以下方法:

  • 在地图视图中使用点按手势识别器
  • 在处理点按的方法中:
    • 将屏幕点按位置转换为地图坐标
    • 遍历每条折线(除非您只有1条)
    • 对于折线中的每个点,采用将该点连接到下一个点的线段,并计算地图坐标远离此线的距离。使用三角学来计算。
      • 如果距离非常接近此段,则停止检查其余段并处理您想要显示的任何标注
      • 如果距离不近,则移动到下一个点以及将其连接到下一个点但只有一个点的线段

无论折线的长度或它们的角度如何,这种方法都可以保证正常工作。没有AABB问题。缺点是所有这些距离计算都可能在计算上很昂贵 - 所以如果您的折线由大量的点组成,或者如果您有大量的折线,那么您可能无法完成所有这些计算在不阻止UI响应的情况下,意味着您需要将其移动到后台线程中。如果你只有一些折线,和/或它们由几个点组成,那么你会没事的。