如何使MKAnnotationView触摸敏感?

时间:2011-12-27 19:04:25

标签: ios iphone objective-c cocoa-touch

我目前有一个地图视图,上面有一些注释。我有自定义图像的注释。我试图解决的问题是图像的敏感性。当我试图拖动它们时,感觉我必须触摸确切的中心才能集中注意力。有没有办法让触摸界更大?

4 个答案:

答案 0 :(得分:18)

为此,您需要继承MKAnnotationView以创建自己的自定义MKAnnotationView。在您的子类中,重写以下函数:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
    // Return YES if the point is inside an area you want to be touchable
}

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    // Return the deepest view that the point is inside of.
}

这允许按下交互式视图(例如按钮等)。 MKAnnotationView中的默认实现对pointInsidehitTest并不严格,因为它允许实际位于一个注释内的印刷机被发送到不同的注释。它通过将最接近的注释中心计算到触摸点并将事件发送到该注释来实现这一点,这使得紧密(重叠)注释不会阻止彼此被选中。但是,在您的情况下,如果用户要选择并拖动最顶层的注释,您可能想要阻止其他注释,因此上述方法可能就是您想要的,否则它会将您设置在正确的路径上。

修改 我在评论中被问到hitTest:withEvent:的示例实现 - 这取决于您要实现的目标。原始问题建议在注释中触摸和拖动图像,而在我的情况下,我在注释中有一些按钮,我想要是交互式的。这是我的代码:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
    UIView* hitView = [super hitTest:point withEvent:event];
    if (hitView != nil)
    {
        // ensure that the callout appears above all other views
        [self.superview bringSubviewToFront:self];

        // we tapped inside the callout
        if (CGRectContainsPoint(self.resultView.callButton.frame, point))
        {
            hitView = self.resultView.callButton;
        }
        else if (CGRectContainsPoint(self.resultView.addButton.frame, point))
        {
            hitView = self.resultView.addButton;
        }
        else
        {
            hitView = self.resultView.viewDetailsButton;
        }
        [self preventSelectionChange];
    }
    return hitView;
}

正如您所看到的那样非常简单 - MKAnnotationView实现(在我的实现的第一行称为super)仅返回第一个(最外层)视图,它不会向下钻取查看层次结构以查看触摸实际位于哪个子视图中。在我的情况下,我只是检查触摸是否在三个按钮之一并返回。在其他情况下,您可以在层次结构中进行简单的基于矩形的钻取或更复杂的命中测试,例如,以避免视图中的透明区域允许触摸通过这些部分。如果确实需要向下钻取,CGRectContainsPoint可以像我使用它一样使用,但请记住将您的点偏移到您钻取的每个视图级别的本地视图坐标。

preventSelectionChange方法是为了防止我的自定义注释被选中,我将其用作地图引脚的可自定义/交互式标注,这样可以保持与选定相关的引脚,而不是允许选择更改为这个注释。

答案 1 :(得分:1)

您是否已将MKAnnotationView子类化,或者您是否更改了刚设置它的图像属性?

以下是设置图像属性的文档。

  

讨论:   为此属性指定新图像还会更改视图框架的大小,使其与新图像的宽度和高度相匹配。视图框架的位置不会改变。

检查注释视图框架的大小,这是对象可以接收触摸的位置。

答案 2 :(得分:0)

我用以下方式实现了类似的东西

  1. 创建处理触摸的Gesture Recognizer类的子类
  2. 创建UIImage类的子类,此类使用识别器类来处理您的手势
  3. 在注释
  4. 中使用此功能

    如果您在图像中的任何位置执行手势识别器子类将处理您的手势。这应该对你有帮助。

    让我们了解此解决方案是否适用于您...

答案 3 :(得分:0)

@jhabbott解决方案从未对我有用,正如我提到here

我有一个图像和一个标签并排。通过设置注释视图image属性来显示图片,并通过添加UILabel

来显示标签

我将func point(inside:with:)方法重定向到UILabel方法(包括图像区域),hitTest确实返回完全相同的视图,无论我点击标签还是图片。但是标签点击没有产生任何回调......

最后,我最后通过放大MKAnnotationView框架来封装标签+图像,我将annotationView.image设置为nil,然后我创建了自定义UIImageView

因为我想在图像中间使用锚点,所以我必须设置一个自定义点:

self.frame = CGRect(x: 0, y: 0, width: 
self.myLabel.frame.width, height: self.myLabel.frame.height)
self.centerOffset = CGPoint(x: self.frame.width/2, y: self.myImageView.frame.height/2)

然后我删除了无效的point(inside:with:)hitTest(point:with:)覆盖。

现在,我的注释视图第一次完全被反应。