4
votes

I have a horizontally scrolling UICollectionView populated with vertically scrolling UITableViews (both being subclasses of UISCrollView). When a scroll gesture begins scrolling in either direction, no other gesture recognizers are recognized until its done decelerating.

So if I scroll horizontally from one tableView to the next, then try to scroll the tableview vertically before deceleration is finished, it will continue scrolling horizontally. This is very frustrating.

1

1 Answers

4
votes

You can get two gesture recognizers to work simultaneously by implementing the UIGestureRecognizerDelegate method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

However, since the delegate for the built in gesture recognizers for UIScrollView MUST be the UIScrollView itself, you must subclass UIScrollView (or UITableView, or UICollectionView) to implement this delegate method.

Kinda defeats the purpose of delegation.

Anyways, now that both UIScrollViews are recognizing gestures simultaneously, we need a way to distinguish horizontal from vertical scroll gestures and make sure the appropriate scroll view handles the appropriate gesture.

A quick solution was to create a vertical swipe gesture recognizer and require that to fail for the horizontal collection view's built in gesture recognizers to recognize.

UISwipeGestureRecognizer* verticalSwipe = [[UISwipeGestureRecognizer alloc] init];
verticalSwipe.direction = UISwipeGestureRecognizerDirectionDown | UISwipeGestureRecognizerDirectionUp;
verticalSwipe.delegate = self;
for (UIGestureRecognizer *gesture in self.collectionView.gestureRecognizers){
    [gesture requireGestureRecognizerToFail:verticalSwipe];
}
[self.collectionView addGestureRecognizer:verticalSwipe];

Then do the same thing for the vertical tableView, adding a horizontal swipe gesture and requiring that to fail for the tableView's built in recognizers to kick in.

    UISwipeGestureRecognizer* horizontalSwipe = [[UISwipeGestureRecognizer alloc] init];
    horizontalSwipe.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
    horizontalSwipe.delegate = self;
    for (UIGestureRecognizer *gesture in tableView.gestureRecognizers){
        [gesture requireGestureRecognizerToFail:horizontalSwipe];
    }
    [tableView addGestureRecognizer:horizontalSwipe];

Adding:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

To BOTH the collectionView and tableView helped to further refine the gesture behavior.