nrj
nrj

Reputation: 1721

iOS: Cancel UIScrollView touches when using 2 fingers

I have written a UIScrollView subclass that I am using to scroll a series of UITableViews. See the following diagram:

enter image description here

As you can see I have several vertically scrolling UITableViews, that are being scrolled horizontally inside a parent UIScrollView. This all works fine. However the application has a number of global gestures. For example, if I swipe in a given direction with 2 fingers, I do a UIView transition to another part of the app. but if I do the gesture on top of the scroll view and/or its child table views, they naturally scroll their content. This doesn't look good and causes some layout issues.

What I would like to figure out is how to disable all scrolling, on both the UIScrollView and its child UITableViews, when a user touches anywhere with two fingers, and only with two fingers. I've tried variations of overriding touchesBegan, touchesEnded, touchesShouldCancel etc... but I can't get it quite right. Any help is much appreciated.

Here is my gesture handling code:

UISwipeGestureRecognizer *twoFingerSwipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerSwipe:)];
[twoFingerSwipeUp setNumberOfTouchesRequired:2];
[twoFingerSwipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[twoFingerSwipeUp setDelegate:self];

// 'self' is the superview of the UIScrollView, which is a UIView.
[self addGestureRecognizer:twoFingerSwipeUp];

[twoFingerSwipeUp release];

// ... repeat the above code for up, down, left, right gestures ...

- (void)handleTwoFingerSwipe:(UISwipeGestureRecognizer*)swipeGesture {

    switch ([swipeGesture direction]) {

        case UISwipeGestureRecognizerDirectionUp:            
            [self changeToView:viewAbove];
            break;

        case UISwipeGestureRecognizerDirectionDown:
            [self changeToView:viewBelow];            
            break;

        case UISwipeGestureRecognizerDirectionRight:
            [self changeToView:viewToTheRight];
            break;

        case UISwipeGestureRecognizerDirectionLeft:
            [self changeToView:viewToTheLeft];
            break;            
    }
}

Upvotes: 4

Views: 3248

Answers (5)

Proud Member
Proud Member

Reputation: 40496

Just disable user interaction in the parent scroll view. You need a UIWindow subclass and override -sendEvent: method because this gets called BEFORE any gesture recognizer. There, if you detect two touches, send a notification. Let the scroll view listen to it and disable user interaction if it occurs. And if touches ended, let it re-enable user interaction.

Upvotes: 0

tarmes
tarmes

Reputation: 15442

One thing that you should be doing is to check that the gesture has finished before acting upon it:

if (swipeGesture.state == UIGestureRecognizerStateEnded) {
   // Do your think
}

I've known odd things to happen otherwise.

Upvotes: 0

Nishith Shah
Nishith Shah

Reputation: 523

Write this code: scrollView.minimumZoomScale=1.0;scrollView.maximumZoomScale=1.0; scrollView.delegate self];

And Here is scrollViewDelegate Method:-

-(UIView*)viewForZoomingInScrollView:(UIScrollView *)aScrollView{ return aScrollView;}

Upvotes: 0

Constantino Tsarouhas
Constantino Tsarouhas

Reputation: 6886

If you're using a swipe recogniser for the two-finger swipe, require the recognisers of the scroll view (including the table views — they're scroll view as well) to fail when the two-finger recogniser recognises its gesture.

[[scrollView panGestureRecognizer] requireGestureRecognizerToFail: twoFingerRecogniser];

Iterate the above code for every scroll view and table view.

(P.S.: "recogniser" is British English, not a spelling err.)

Hope that helps. :-)

Upvotes: 1

Ole Begemann
Ole Begemann

Reputation: 135548

Try setting panGestureRecognizer.maximumNumberOfTouches = 1 on all scroll and table views (iOS 5 only).

Upvotes: 1

Related Questions