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

发布于 2024-11-26 20:26:31 字数 589 浏览 4 评论 0原文

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

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

我已确保将 userInteractionEnabled 设置为 YES,并且研究了如何将触摸发送到自定义注释视图(我的 MKAnnotationView 的子类)覆盖 touchesBegan 等 - 但看起来触摸通常会被取消(我认为我已经设法获得 touchesEnded 几次) - 所以看起来它甚至会难以手动使用自定义注释视图实现任何用户交互。

有谁对允许更多用户与 MKAnnotationView 对象进行交互有任何见解吗?

I have a custom annotation view on the map, which has a UIButton in it, but the UIButton is not responsive when pressed. I have two main problems with user interaction on the annotation view:

  1. Buttons and other controls are not responsive.
  2. I want the annotation to block touches according to my implementation of - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event - that is if I return YES then I don't want the touches to get sent through to the MKMapView (potentially selecting other annotations that are BEHIND my annotation view), I want to handle the touch myself in this case.

I have made sure userInteractionEnabled is set to YES and I have investigated how touches are sent to the custom annotation view (my subclass of MKAnnotationView) by overriding touchesBegan etc. - but it appears that the touches are usually cancelled (thought I've managed to get touchesEnded a few times) - so it seems like it will even be difficult to manually implement any user-interaction with the custom annotation view.

Does anyone have any insights into allowing more user interaction with MKAnnotationView objects?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

執念 2024-12-03 20:26:31

我在同事的帮助下成功解决了这个问题。解决方案是重写 - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event。我们的假设是 MKAnnotationView (您的注释视图必须继承它)会覆盖它以执行“错误”的操作(大概是这样注释选择不会在重叠注释之间​​被阻止)。因此,您必须重新重写它才能做正确的事情并返回适当的 UIView,然后系统将向其发送事件,用户将能够与其交互:)。这具有有益的(在本例中)副作用,即交互式注释会阻止对其后面的注释的选择。

I managed to resolve this with the help of a colleague. The solution is to override - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event. Our assumption is that MKAnnotationView (which your annotation view must inherit from) overrides this to do the 'wrong' thing (presumably so that annotation selection doesn't get blocked between overlapping annotations). So you have to re-override it to do the right thing and return the appropriate UIView, the system will then send the events to it and the user will be able to interact with it :). This has the beneficial (in this case) side-effect that the interactive annotation blocks the selection of annotations that are behind it.

淡淡の花香 2024-12-03 20:26:31

我发现,我可以直接覆盖 pointInside:withEvent: ,而不是重写 hitTest: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;
}

I found that rather than overriding hitTest:withEvent: I could just override pointInside:withEvent: instead and just get it to return YES. I guess that officially I should be doing a point-rect intersect check to ensure the place I'm tapping is within the control element, but in practise, just putting return YES appears to work perfectly well, still allowing you to dismiss the MKAnnotationView by tapping away from it.

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

    return YES;
}
等你爱我 2024-12-03 20:26:31

加上 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 可能不是必需的。

Adding up to the answer of jhabbott, this is what worked for me. I have a custom annotation view MKCustomAnnotationView that holds a custom annotation CustomPin as annotation. That 'pin' holds a UIButton as accessory button replacement which I wanted to get touch events.

My hitTest method would look like this:

- (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;
}

The calloutActive bool is probably not necessary in most cases.

七堇年 2024-12-03 20:26:31

对于任何想要将 tapGesture 添加到 AnnotationView 子视图的人,答案在底部:

MKannotationView 以 UIButton 作为子视图,按钮不响应

对我有用:

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

For anyone looking to add a tapGesture to an AnnotationView subview then the answer at the bottom of this:

MKannotationView with UIButton as subview, button don't respond

Worked for me:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (CGRectContainsPoint(_button.frame, point)) {
        return _button;
    }
    return [super hitTest:point withEvent:event];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文