将UIButton和其他UIControl对象放入MKAnnotationView中并允许用户交互



我在地图上有一个自定义注释视图,其中有一个UIButton,但是UIButton在按下时没有响应。我在注释视图上的用户交互有两个主要问题:

  1. 按钮和其他控件没有响应
  2. 我想要注释阻止触摸根据我的- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event的实现-也就是说,如果我返回YES,然后我不希望触摸通过发送到MKMapView(潜在地选择其他注释在我的注释视图后面),我想在这种情况下处理触摸自己。

我已经确保userInteractionEnabled被设置为YES,我已经调查了如何通过重写touchesBegan等来发送触摸到自定义注释视图(我的MKAnnotationView子类)-但似乎触摸通常被取消(认为我已经设法获得touchesEnded几次)-所以看起来它甚至很难手动实现任何用户交互与自定义注释视图。

有没有人对允许更多用户与MKAnnotationView对象交互有任何见解?

我在一位同事的帮助下设法解决了这个问题。解决方案是覆盖- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event。我们的假设是MKAnnotationView(你的注释视图必须继承)覆盖这做"错误"的事情(大概是这样的注释选择不会被重叠的注释之间阻塞)。所以你必须重新覆盖它来做正确的事情,并返回适当的UIView,然后系统将发送事件给它,用户将能够与它交互:)。这有一个有益的副作用(在这种情况下),即交互式注释阻止了它后面的注释的选择。

我发现,而不是覆盖hitTest:withEvent:,我可以覆盖pointInside:withEvent:,而不是让它返回YES。我猜正式我应该做一个点-矩形相交检查,以确保我点击的地方是在控制元素,但在实践中,只是把return YES似乎工作得很好,仍然允许你通过点击离开它来驳回MKAnnotationView。

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{   
    // for testing purposes
    BOOL result = [super pointInside:point withEvent:event];
    NSLog(@"pointInside:RESULT = %i", result);
    return YES;
}

把jhabbott的答案加起来,这就是我的工作。我有一个自定义注释视图MKCustomAnnotationView,它将自定义注释CustomPin保存为注释。那个'pin'持有一个UIButton作为附件按钮的替代品,我想获得触摸事件。

我的hitTest方法看起来像这样:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *result = [super hitTest:point withEvent:event];
    //NSLog(@"ht: %f:%f %d %@", point.x, point.y, [[event touchesForView:self] count], result);
    if ([result isKindOfClass:[MKCustomAnnotationView class]])
    {
        MKCustomAnnotationView *av = (MKCustomAnnotationView *)result;
        CustomPin *p = av.annotation;
        UIButton *ab = p.accessoryButton;
        if (p.calloutActive && point.x >= ab.frame.origin.x)
            return ab;
    }
    return result;
}

calloutActive bool在大多数情况下可能是不必要的。

对于任何想要将tapGesture添加到AnnotationView子视图的人来说,下面的答案是:

MKannotationView with UIButton作为子视图,button don't response

working for me:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (CGRectContainsPoint(_button.frame, point)) {
        return _button;
    }
    return [super hitTest:point withEvent:event];
}

最新更新