A nice way of doing this without messing about with only starting to pan when you've moved a certain value is to determine which direction the gesture recognizer has translated the most in and using that. It cuts down on the amount of code you need quite a bit and works fairly well in my testing.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
CGPoint translation = [(UIPanGestureRecognizer*)gestureRecognizer translationInView:self.superview];
return fabsf(translation.x) > fabsf(translation.y)
}
return YES;
}
And now your view sliding becomes simpler. This code allows you to drag in either direction.
- (void)drag:(UIPanGestureRecognizer *)sender {
CGPoint translation = [sender translationInView:self.superview];
CGRect frame = self.upperView.frame;
switch (sender.state) {
case UIGestureRecognizerStateChanged:
frame.origin.x = translation.x;
[self.upperView setFrame:frame];
break;
case UIGestureRecognizerStateBegan:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateFailed:
default:
break;
}
}
Additionally, you may want to allow your gesture recognizer to work along side others (as in, the recognizer that handles the scrolling of the table view) but the code in gestureRecognizerShouldBegin:
seems to handle this without issue.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Also note that I'm using self.superview
instead of just self
as you have. This is because of this line in the translationInView:
section of the docs:
The view in whose coordinate system the translation of the pan gesture should be computed. If you want to adjust a view's location to keep it under the user's finger, request the translation in that view's superview's coordinate system.