【问题标题】:Putting UIButton and other UIControl objects inside an MKAnnotationView and allowing user interaction将 UIButton 和其他 UIControl 对象放入 MKAnnotationView 并允许用户交互
【发布时间】:2011-07-28 17:10:47
【问题描述】:

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

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

我已经确定 userInteractionEnabled 设置为 YES 并且我已经调查了如何通过覆盖 touchesBegan 等将触摸发送到自定义注释视图(我的 MKAnnotationView 子类) - 但似乎触摸通常会被取消(我想我已经成功获得了touchesEnded 几次) - 所以似乎很难手动实现与自定义注释视图的任何用户交互。

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

【问题讨论】:

  • 您能否发布一些代码来说明如何将 UIControls 添加到 MKAnnotationView?
  • 最好将按钮放在标注中,而不是注释中
  • @Pennypacker 我有一个 UView,其中嵌套了控件,这个 UIView 也用于应用程序的其他地方。 UIView 已添加到我的自定义注释视图中。
  • @xs2bush 标注不能像注释那样自定义,这需要通过注释来完成。
  • 我添加了按钮来标注为右或左附件视图......它完全有效

标签: iphone ipad mapkit mkannotation mkannotationview


【解决方案1】:

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

【讨论】:

  • 我仍在尝试自己解决如何实现这一点...您是覆盖MKAnnotationView 中的hitTest:withEvent: 还是MKMapView?如果是MKMapView,这是否意味着我需要对其进行子类化才能覆盖该方法?您需要返回哪个视图,rightCalloutAccessoryView 还是 MKAnnotationView
  • Subclass MKAnnotationView 使用您的自定义视图类并覆盖 hitTest:withEvent: - 从这里您可以返回视图本身或其子视图之一(例如按钮或其他交互式对象) - 触摸将被发送到该视图。
  • 奇怪的是,这对我不起作用。我唯一能开始工作的就是实现pointInside:withEvent 并返回YES。即使这样,它也适用于普通的 pin 注释,但两种方法都不适用于用户位置 pin 注释。
【解决方案2】:

我发现与其覆盖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;
}

【讨论】:

  • 如果您只覆盖pointInside:withEvent,那么您的交互式注释后面的任何其他注释仍然可以被选中,从而取消选择活动注释。您需要覆盖 hitTest:withEvent 以阻止触摸被发送到其他重叠(即后面)注释。
  • 所以当你覆盖 pointInside:withEvent: 时,你是否只是返回 nil 以阻止它冒泡?
  • 不,我假设“冒泡”是指弹出的标注?我的问题/解决方案是当您根本不使用标注(因为它们不是很可定制)而使用自定义注释(当您选择其他“pin”注释之一时添加自定义注释)时。
【解决方案3】:

加上 jhabbott 的答案,这对我有用。我有一个自定义注释视图MKCustomAnnotationView,其中包含一个自定义注释CustomPin 作为注释。那个“别针”有一个 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 在大多数情况下可能不是必需的。

【讨论】:

    【解决方案4】:

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

    MKannotationView with UIButton as subview, button don't respond

    为我工作:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多