I've got a UIScrollView
with paging enabled, and I've added my own UIPanGestureRegonizer
to it. Under certain instances, my view controller will set scrollview.scrollEnabled = NO
, and then add the pan gesture recognizer to it (I'm not using the scrollview's own recognizer).
So, scrolling is disabled but I'm waiting for user touches from my gesture recognizer. When it recognizes, it calls its action in which I re-enable scrolling.
The problem is, while the user still has a finger down, my scrollview doesn't track with the finger. It doesn't start scrolling until the finger is lifted and then dragged again. So my gesture recognizer is swallowing all the touches and not forwarding any to the scrollview.
I've tried toggling panGestureRecognizer.cancelsTouchesInView = NO;
but it doesn't seem to have any effect (I'm currently removing this recognizer as soon as I re-enable scrolling but whether I do this or not doesn't solve my problem). I've also looked into the delays...
properties of UIGestureRecognizer
but they don't seem to be helping, either.
Any ideas? How can I get these events to continue to forward to my scrollview?
The answer is a bit easier if you are only targeting iOS 5 and up, because in that case you really ought to reuse the UIScrollView panGestureRecognizer property.
In any case, the key step is to NOT reuse scrollEnabled, but instead to subclass UIScrollView, create your own property to manage this state, and override setContentOffset:.
- (void) setContentOffset:(CGPoint)contentOffset
{
if(self.programaticScrollEnabled)
[super setContentOffset:contentOffset];
}
Here's one possible iOS 4+ Solution:
- Subclass UIScrollView (or subclass another subclass of UIScrollView, depending on your needs).
- Override all the initializers to ensure your setup code is called.
- Declare the BOOL property and override setContentOffset: as described above.
In your setup code, set up a UIPanGestureRecognizer and set your state variable to allow programatic scrolling (assuming that's the default state you want):
panRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)] autorelease]; //These properties may change according to your needs panRecognizer.cancelsTouchesInView = NO; panRecognizer.delaysTouchesBegan = NO; panRecognizer.delaysTouchesEnded = NO; [self addGestureRecognizer:panRecognizer]; panRecognizer.delegate = self; self.programaticScrollEnabled = YES;
Manage which gestures can occur simultaneously. In my case:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; }
Turn programatic scrolling back on wherever you need it. For example:
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer { self.programaticScrollEnabled = YES; } - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { self.programaticScrollEnabled = YES; return YES; }
来源:https://stackoverflow.com/questions/8718073/continuous-scrolling-between-uipangesturerecognizer-and-re-enabled-uiscrollview