开发者

MKMapview with UIGestureRecognizers

开发者 https://www.devze.com 2023-03-23 12:19 出处:网络
So I have a UIView as my Root view on my iPad. I add some subviews to it, amongst which there\'s also an MKMapView.

So I have a UIView as my Root view on my iPad. I add some subviews to it, amongst which there's also an MKMapView.

The thing I am trying to achieve ist to detect a 3-finger swipe across the screen so I can react to it. Furthermore I need to distinguish between 3-finger swipe to the left or to the right.

Before I added the mapview, I was experimenting with touchesMoved etc. Since I found out this to be inaccurate, I moved to using UISwipegestureRecognizer which worked well.

Anyway, once I added the Map, it ate all my touches. So I kept looking for answers.

This one seemed promising:

Intercepting/Hijacking iPhone Touch Events for MKMapView

as well as subclassing UIWindow and intercepting the touches.

Well, it turns out, none of them work well for me, since in both cases I end up either in

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

or in the situation to recognize the touch typ开发者_如何学Ce etc. This is, what I was trying to do in first place!

So my question is: Is there a way to use UIGestureRecognizers the way I described above to maintain my controls while keeping the functionality of the Mapview?

Have I decribed my problem accurately enough?

Greetz.


This answer describes subclassing a gesture recogniser to ensure that it does not interfere with other recognisers.

You could add a custom recogniser to MKMapView that intercepts three finger swipe (and reacts appropriately) but then allows all other gestures to be processed as normal by the MKMapView.

The link above give the example adding simple finger press by subclassing UIGestureRecognizer. For a three finger swipe I would subclass UISwipeGestureRecognizer.

I have had success using this method to add two finger rotate to a MKMapView without messing up pan and zoom etc.


The map should not "eat" all your touches. There's something wrong with that - I have successfully added long press and tap recognizers to the MKMapView, and they worked as expected.

Make sure to assign your controller the delegate of all the gesture recognizers you create, and be sure to implement the method:

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

You can gain further control by implementing

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

After that, it's very much up to the details of your implementation to make the gesture recognizer work with the map view. In my experience you can add your own, and it should not be interfering with your recognizers.

Some other thoughts: - Overlay an invisible user interaction enabled view over the MKMapView to take events from it. Depending on how much interaction you need on the map view you could turn this on and off, etc. - Add another swipe recognizer to the map view itself (in addition to the one on the parent view).

You could also play around with UIView hitTest method but for me that was always too low level.


question is old, but actual. my two cents, especially for OSX If You need to detect pinch from region changes by code: (I set an ivar to detect in in orther places of controller code)

 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
    }


Would removing the swipe gesture recognizer from your MkMapView resolve the issue?

UISwipeGestureRecognizer *leftSwipeGesture = [[UISwipeGestureRecognizer alloc] init];
UISwipeGestureRecognizer *rightSwipeGesture = [[UISwipeGestureRecognizer alloc] init];

leftSwipeGesture.direction = UISwipeGestureRecognizerDirectionLeft;
rightSwipeGesture.direction = UISwipeGestureRecognizerDirectionRight;

[YourMKMapView removeGestureRecognizer:leftSwipeGesture];
[YourMKMapView removeGestureRecognizer:rightSwipeGesture];

That way, MKMapView will not respond to swipe gestures and resigns responder to the container view controller of the MKMapView.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号