I am attempting to implement a UIScrollView where horizontally panning scrolls through pictures in the scrollview but vertically panning performs another action I have. Right now I have a UIScrollView that is paginated with vertical scrolling disabled that works just fine for scrolling through pictures, but am going crazy trying to find a way to intercept vertical pans and call my own method instead of the vertical pans just being eaten up by the scrollview. I was able to do
UIPanGestureRecognizer *panUp = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
[self.scrollView addGestureRecognizer:panUp];
[scrollView.panGestureRecognizer setEnabled:NO];
Which gives me total control over the panning in my handlePanGesture: method, but this isn't particularly helpful because then I feel like I am essentially going to be rewriting all the scrolling logic which I am trying to avoid. Any help or guidance on how to achieve this would be greatly appreciated.
Thanks!
As of iOS 5, UIScrollView
exposes its UIPanGestureRecognizer
. Set your custom swipe’s delegate
to self
and make the gestureRecognizer a property or ivar, and make your class conform to the <UIGestureRecognizerDelegate>
protocol. Then, implement UIGestureRecognizerDelegate
’s – gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
like so:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isEqual:self.swipe] && [otherGestureRecognizer isEqual:self.scrollView.panGestureRecognizer])
{
return NO;
}
return YES; // the default for this method
}
I think this will be difficult if you want to use a pan gesture because of the scroll view's use of those gestures. However, if you could use a swipe, it is easy to implement.
UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
swipe.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
[self.scrollView addGestureRecognizer:swipe];
I tested this, and it worked fine to call the handler, and you don't need to disable the scroll view's pan gesture recognizer (in my test, the scroll view was tall enough and the content short enough that there was no vertical scrolling -- I don't know if this is necessary or not).
I added a UIPanGestureRecognizer
then setupgestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
like this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([gestureRecognizer isEqual:self.panGesture] && [otherGestureRecognizer isEqual:self.collectionView.panGestureRecognizer]){
return YES;
}
return NO;
}
I also added a check in gestureRecognizerShouldBegin:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isEqual:self.panGesture]) {
if (gestureRecognizer.numberOfTouches > 0) {
CGPoint point = [gestureRecognizer locationOfTouch:0 inView:gestureRecognizer.view];
CGFloat distX = abs(self.collectionView.lastTouchPos.x - point.x);
CGFloat distY = abs(self.collectionView.lastTouchPos.y - point.y);
if (distX > distY) {
return NO;
}
} else {
return NO;
}
}
return YES;
}
to only use self.panGesture
when panning up or down.
Update
https://stackoverflow.com/a/8603839/667834 appears to have a better method for gestureRecognizerShouldBegin
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isEqual:self.panGesture]) {
if (gestureRecognizer.numberOfTouches > 0) {
CGPoint translation = [self.panGesture velocityInView:self.collectionView];
return fabs(translation.y) > fabs(translation.x);
} else {
return NO;
}
}
return YES;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With