So, I figured it out.
First, I set the web view delegate to get scroll events and check if the web view scrolls up or down:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { if([scrollView isEqual:webView.scrollView]) { float contentHeight = scrollView.contentSize.height; float height = scrollView.frame.size.height; float offset = scrollView.contentOffset.y; if(offset == 0) { webViewScrolledToTop = true; webViewScrolledToBottom = false; } else if(height + offset == contentHeight) { webViewScrolledToTop = false; webViewScrolledToBottom = true; } else { webViewScrolledToTop = false; webViewScrolledToBottom = false; }
Then I registered additional gesture recognizers when viewing the webview scroll:
swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeUp)]; swipeUp.direction = UISwipeGestureRecognizerDirectionUp; swipeUp.delegate = self; [self.webView.scrollView addGestureRecognizer:swipeUp]; [self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeUp]; swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeDown)]; swipeDown.direction = UISwipeGestureRecognizerDirectionDown; swipeDown.delegate = self; [self.webView.scrollView addGestureRecognizer:swipeDown]; [self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeDown];
Note the calls to [self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeUp];
. This is absolutely necessary, because without them, a web-based gesture recognizer will always consume events before they reach the gesture recognizer. These challenges change priorities.
In the swipeUp and swipeDown methods, I calculate the position of the next “page” and scroll the parent scroll view to that position if there really is a next page.
The last thing to check is if the webview scrolls up or down and only accepts gestures in this case. To do this, you need to implement the gesture recognizer delegate:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if(gestureRecognizer == swipeUp) { return webViewScrolledToBottom; } else if(gestureRecognizer == swipeDown) { return webViewScrolledToTop; } return false; }
You may also need to disable scroll scans so that this work with such small web pages that they do not scroll at all: webView.scrollView.bounces = false;
source share