I\'m using a UIPanGestureRecognizer to recognize horizontal sliding in a UITableView (on a cell to be precise, though it is added to the table itself). However, this gesture rec
Thanks for the tips! I eventually went for a UITableView subclass, where i check if the movement is horizontal (in which case i use my custom behaviour), and else call [super touchesMoved: withEvent:];.
However, i still don't really get why this works. I checked, and super is a UITableView. It appears i still don't fully understand how this hierarchy works. Can someone try and explain?
I had the same issue and came up with a solution that works with the UIPanGestureRecognizer.
In contrast to Erik I've added the UIPanGestureRecognizer to the cell directly, as I need just one particular cell at once to support the pan. But I guess this should work for Erik's case as well.
Here's the code.
- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
UIView *cell = [gestureRecognizer view];
CGPoint translation = [gestureRecognizer translationInView:[cell superview]];
// Check for horizontal gesture
if (fabsf(translation.x) > fabsf(translation.y))
{
return YES;
}
return NO;
}
The calculation for the horizontal gesture is copied form Erik's code – I've tested this with iOS 4.3.
Edit: I've found out that this implementation prevents the "swipe-to-delete" gesture. To regain that behavior I've added check for the velocity of the gesture to the if-statement above.
if ([gestureRecognizer velocityInView:cell].x < 600 && sqrt(translate...
After playing a bit on my device I came up with a velocity of 500 to 600 which offers in my opinion the best user experience for the transition between the pan and the swipe-to-delete gesture.
My answer is the same as Florian Mielke's, but I've simplified and corrected it some.
Simply give your UIPanGestureRecognizer
a delegate (UIGestureRecognizerDelegate
). For example:
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDetected:)];
panner.delegate = self;
[self addGestureRecognizer:panner];
Then have that delegate implement the following method:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
CGPoint translation = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:gestureRecognizer.view.superview];
return fabsf(translation.x) > fabsf(translation.y);
}
You may try using the touch events manually instead of the gesture recognizers. Always passing the event back to the tableview except when you finally recognize the swipe gesture.
Every class that inherits from UIResponder will have the four touch functions (began, ended, canceled, and moved). So the simplest way to "forward" a call is to handle it in your class and then call it explicitly on the next object that you would want to handle it (but you should make sure to check if the object responds to the message first with respondsToSelector: since it is an optional function ). This way, you can detect whatever events you want and also allow the normal touch interaction with whatever other elements need it.
Maybe you can use the UISwipeGestureRecognizer
instead? You can tell it to ignore up/down swipes via the direction
property.