UIWebView delegate vertical scroll event to parent, if scrolled to top or bottom

可紊 提交于 2019-12-03 16:41:02

So, I figured it out.

First I set the delegate of the webview, so that I get scroll events and can check, if the webview is scrolled to top or bottom:

- (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;
        }

        //NSLog(@"Webview is at top: %i or at bottom: %i", webViewScrolledToTop, webViewScrolledToBottom);
    }
}

Then I registered additional swipe gesture recognizers at the webview's scrollview:

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];

Notice the calls to [self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeUp];. Those are absolutely necessary, because without them, the pan gesture recognizer of the webview would always consume the events, before they reach the swipe gesture recognizer. Those calls change the priorities.

In the swipeUp and swipeDown methods, I calculate the position of the next "page" and scroll the parent scroll view to this position, if there actually is a next page.

Last thing is, to check, if the webview is scrolled to top or bottom and only accept the gestures in that case. Therefor you have to implement the delegate of the gesture recognizer:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if(gestureRecognizer == swipeUp) {
        return webViewScrolledToBottom;
    } else if(gestureRecognizer == swipeDown) {
        return webViewScrolledToTop;
    }

    return false;
}

You might also have to disable the scroll bouncing to make this work with webpages, which are so small, that they are not scrolled at all:webView.scrollView.bounces = false;

Is it really the scrollview which scrolls vertically or is it the webview? I haven´t tried it myself, but maybe this will help...

webView.scrollView.scrollEnabled = NO; 
webView.scrollView.bounces = NO;

or ...

webView.userInteractionEnabled = NO;

I have done this before, but I ended using Javascript and Obj-c. I added a function that checks (with JQuery) if the page is at the bottom or the top of the scroll (I needed that for my App). Then I call that function with a NSTimer using:

NSString *str= [webView stringByEvaluatingJavaScriptFromString:@"JSFunction()"];

I know its kind of ugly, but it was the only way I found to do this at the time, and it just do the job. Here's the code I used:

function JSFunction() {
    var docHeight = $(document).height();
    var scroll    = $(window).height() + $(window).scrollTop();
    if (docHeight == scroll || $(window).scrollTop() < 10)
                 return "TOP";
            else
                 return "BODY";
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!