Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use UIScreenEdgePanGestureRecognizer without moving MKMapView

I have a UIViewController containing a MKMapView (in fact, it contains a full screen container containing the MKMapView, but it shouldn't have any impact)

I implemented a UIScreenEdgePanGestureRecognizer (to show a drawer) like this:

self.swipeRight = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleEdgeGesture:)];
[self.swipeRight setEdges:UIRectEdgeLeft];
[self.swipeRight setDelegate:self];
[self.view addGestureRecognizer:self.swipeRight];

and to make it works I had to add the following method (returning YES):

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

But then the map is moving at the same time as the drawer is appearing! I've tried all kind of tricks to prevent it but was not able to... (I tried shouldBeRequiredToFailByGestureRecognizeror requireGestureRecognizerToFail for example)

Any idea how I could prevent the MapView from moving when the gesture is a ScreenEdgePan from LeftEdge?

like image 225
Sebastien C. Avatar asked Jul 18 '14 20:07

Sebastien C.


3 Answers

What I did in my app was the following:

UIScreenEdgePanGestureRecognizer *popRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePopRecognizer:)];
popRecognizer.edges = UIRectEdgeLeft;
popRecognizer.delegate = self;

Then set the delegate to YES as you said

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

And enable/disable scrolling of the mapview like this

- (void)handlePopRecognizer:(UIScreenEdgePanGestureRecognizer*)recognizer
{
    if(recognizer.state == UIGestureRecognizerStateBegan){
        _mapView.scrollEnabled = NO;
    } else if(recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled){
        _mapView.scrollEnabled = YES;

    }
}

Hope it helps.

like image 102
Cedrick Avatar answered Nov 07 '22 05:11

Cedrick


The pan gesture on the map needs to be cancelled as soon as the UIScreenEdgePanGestureRecognizer begins to recognize. To achieve this it is sufficient to set scrollEnabled to NO momentarily. This will cancel the other gesture recognizer.

- (void) handleEdgeGesture:(UIScreenEdgePanGestureRecognizer*)recognizer
{
    if(recognizer.state == UIGestureRecognizerStateBegan) {
        // cancel simultaneous gesture on map view
        _mapView.scrollEnabled = NO;
        _mapView.scrollEnabled = YES;
    }
}
like image 20
Felix Avatar answered Nov 07 '22 04:11

Felix


The following combination worked for me without touching the map view.

// This is to ensure UIScreenEdgePanGestureRecognizer won't be blocked by other gestures. 
// You may need to do some logic checking before returning YES.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
  return YES;
}
// This is to prevent other recognisers when UIScreenEdgePanGestureRecognizer
// is recognising the gesture. Again, you may want to do some logic checking
// before returning to YES.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{

  return YES;
}
like image 24
Mingming Avatar answered Nov 07 '22 04:11

Mingming