【问题标题】:MKMapview with UIGestureRecognizers带有 UIGestureRecognizers 的 MKMapview
【发布时间】:2011-07-26 10:50:53
【问题描述】:

所以我有一个 UIView 作为我 iPad 上的根视图。我添加了一些子视图,其中还有一个 MKMapView。

我想要实现的目标是检测 3 指在屏幕上的滑动,以便对它做出反应。此外,我需要区分三指向左或向右滑动。

在添加地图视图之前,我正在尝试使用 touchesMoved 等。由于我发现这不准确,我转而使用 UISwipegestureRecognizer,效果很好。

无论如何,一旦我添加了地图,它就吃掉了我所有的触摸。所以我一直在寻找答案。

这个看起来很有希望:

Intercepting/Hijacking iPhone Touch Events for MKMapView

以及子类化 UIWindow 和拦截触摸。

好吧,事实证明,它们都不适合我,因为在这两种情况下,我最终都在

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

或在识别触摸类型等的情况下。 这就是我最初想要做的!

所以我的问题是:有没有办法按照我上面描述的方式使用 UIGestureRecognizers 来维护我的控件,同时保持 Mapview 的功能?

我是否足够准确地描述了我的问题?

问候。

【问题讨论】:

  • 您是否实现了所有 UIGestureRecognizerDelegate 方法,以便您的地图可以与地图一起被识别(或者如果您愿意,可以互相阻止)?

标签: iphone ipad mkmapview uigesturerecognizer touch-event


【解决方案1】:

This answer 描述了对手势识别器进行子类化以确保它不会干扰其他识别器。

您可以向 MKMapView 添加一个自定义识别器,该识别器拦截三指滑动(并做出适当反应),但随后允许 MKMapView 正常处理所有其他手势。

上面的链接给出了通过继承 UIGestureRecognizer 添加简单手指按压的示例。对于三指滑动,我将继承 UISwipeGestureRecognizer。

我已经成功使用此方法将两个手指旋转添加到 MKMapView 而不会弄乱平移和缩放等。

【讨论】:

    【解决方案2】:

    地图不应该“吃掉”你所有的触摸。这有点问题 - 我已成功地将长按和点击识别器添加到 MKMapView,并且它们按预期工作。

    确保为您的控制器分配您创建的所有手势识别器的委托,并确保实现该方法:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer  shouldRecognizeSimultaneouslyWithGestureRecognizer :(UIGestureRecognizer *)otherGestureRecognizer;
    

    您可以通过实施获得进一步的控制权

     -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
    

    之后,要让手势识别器与地图视图一起工作,很大程度上取决于您的实现细节。根据我的经验,您可以添加自己的,它不应该干扰您的识别器。

    其他一些想法: - 在 MKMapView 上覆盖一个不可见的用户交互启用视图以从中获取事件。根据您在地图视图上需要多少交互,您可以打开和关闭它,等等。 - 将另一个滑动识别器添加到地图视图本身(除了父视图上的那个)。

    您也可以使用 UIView hitTest 方法,但对我来说这总是太低级了。

    【讨论】:

    • 我遇到了一个问题,我的地图视图中的手势识别器会调用我的操作方法,直到我开始显示用户的位置。这解决了它。谢谢!
    【解决方案3】:

    问题很老,但很实际。我的两分钱,尤其是对于 OSX 如果您需要通过代码检测区域变化的夹点: (我在控制器代码的其他地方设置了一个 ivar 来检测)

     func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
            guard let view = mapView.subviews.first else{ return }
    
            self.regionChangeIsFromUserInteraction = false
    
            #if os(iOS)
            guard let recognizers = view.gestureRecognizers else{ return }
            #elseif os(OSX)
            // on OSX they are in maps..
            let recognizers = mapView.gestureRecognizers
            #endif
    
            for recognizer : AimGestureRecognizer in recognizers{
                let state = recognizer.state
                if state == .began || state == .ended {
                    self.regionChangeIsFromUserInteraction = true
                    break
                }
            }
    
            #if DEBUG
            print("regionChangeIsFromUserInteraction ", self.regionChangeIsFromUserInteraction)
            #endif
        }
    

    【讨论】:

      【解决方案4】:

      从您的 MkMapView 中移除滑动手势识别器会解决问题吗?

      UISwipeGestureRecognizer *leftSwipeGesture = [[UISwipeGestureRecognizer alloc] init];
      UISwipeGestureRecognizer *rightSwipeGesture = [[UISwipeGestureRecognizer alloc] init];
      
      leftSwipeGesture.direction = UISwipeGestureRecognizerDirectionLeft;
      rightSwipeGesture.direction = UISwipeGestureRecognizerDirectionRight;
      
      [YourMKMapView removeGestureRecognizer:leftSwipeGesture];
      [YourMKMapView removeGestureRecognizer:rightSwipeGesture];
      

      这样,MKMapView 将不会响应滑动手势并将响应者辞职给 MKMapView 的容器视图控制器。

      【讨论】:

      • 听起来很有趣,会尽快尝试反馈
      • 这实际上没有帮助。我没有错过任何东西,是吗?
      • 不起作用,因为地图的识别器不直接在 MKMapView 上。将 MKMapView 视为一堆分层视图、手势识别器和识别器委托。它从 iOS 5 到 iOS 6 非常不同 - 它可能会在 iOS 7 中再次发生变化,因为没有任何内部通过 API 公开。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多