Nested UIScrollViews scrolling simultaneously

2019-04-28 09:39发布

问题:

I have two nested UIScrollViews: the parent limited to horizontal paging and the child limited to vertical scrolling. The content is one large view that can be freely dragged around, but snaps to one of three horizontal sections. The default behavior of the nested scroll views is to only allow scrolling in one direction at a time, but I wanted to allow simultaneous dragging in both direction to maintain the feeling of manipulating a single large view.

My present solution involved isolating the vertical scroll view's gesture and setting its delegate to my view controller:

for (UIGestureRecognizer *gesture in scrollView.gestureRecognizers)
    if ([gesture isKindOfClass:[UIPanGestureRecognizer class]])
        gesture.delegate = self;

Then, I implemented the delegate method to allow the gestures of the paging view to recognize simultaneously with the pan gesture of the scroll view:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if (gestureRecognizer.view == scrollView && otherGestureRecognizer.view == pageView)
        return YES; // allow simultaneous scrolling of pageView and scrollView

    return NO;
}

This solution mostly works, but it will occasionally act glitchy when I drag the view around, particularly when I move it around quickly with mouse or drag it around past the view bounds. Specifically, one of the scroll views will temporarily jump back to where it started as if that gesture had been canceled, but then it will jump back if I keep scrolling.

What I want to know is if there is a simpler or more reliable method to achieve scrolling like this that I've overlooked, or if there's anything that I can do to eliminate the glitchy behavior.

回答1:

The glitchy behavior was happening when the views were dragged out of the content area, released, and then tapped/dragged again before the scroll views bounced back. This could happen, for example, when the view was scrolled by several small swipes. One of the scroll views would get confused and try to decelerate (bounce) while simultaneously being dragged, causing it to jitter back and forth between the origin and where it had been dragged to.

I was able to fix this by reversing the nesting of the scroll views (paging view inside of the vertical scrolling view) and by adding the delegate to the paging view's UIPanGestureRecognizer instead of to the scrolling view's gesture. Now it scrolls naturally as if it was a single scroll view while still conforming to paging only in the horizontal direction. I don't think it was intended for scroll views to be tricked into scrolling simultaneously like this, so I'm not sure if the original glitchy behavior was the result of a bug, or just a consequence of doing something unintended.



回答2:

Just been struggling with this too and hit a wall with 'NSInvalidArgumentException', reason: 'UIScrollView's built-in pan gesture recognizer must have its scroll view as its delegate.' as pointed out by Rythmic Fistman above.

Found a way around it... first subclass the inner UIScrollView and make it as a

Then all you have to do in the implementation is:

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

Seems to work fine.