3

I am trying to achieve pull to refresh in a WKWebView like in this Material pull to refresh GIF. Because we want to include websites that already have a html navigation bar, we need to keep the web view fix when dragging down. I found pull to refresh (UIRefreshControl) to table views and web views but the views go down as the user drags down.

I set the delegate to scrollView property of the web view and receive notifications. When I drag near to top and get to 0 (vertical scroll view offset) I can disable the scroll view, enable the pan gesture. But to actually move the custom spinner view I need a second touch.

The method func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) doesn't work because I have a scroll view over.

private func gestures() {

    self.panGesture = UIPanGestureRecognizer(
        target: self,
        action: "panGestureCaptured:"
    )
    self.panGesture!.enabled = false
    self.webView.addGestureRecognizer(self.panGesture!)
}

func scrollViewDidScroll(scrollView: UIScrollView) {

    if scrollView.contentOffset.y <= 0 {
    self.view.layoutIfNeeded()
        self.spinnerTopLayoutConstraint?.constant = -scrollView.contentOffset.y
    }
}

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {

    if scrollView.panGestureRecognizer.translationInView(scrollView.superview).y > 0 { // dragging down

        if scrollView.contentOffset.y == 0 {

            self.webView!.scrollView.scrollEnabled = false
          //  self.webView!.scrollView.canCancelContentTouches = true
            self.panGesture!.enabled = true
            // self.refreshWebView()


        }

        self.showNavigationItems()


    } else { // dragging up
        self.hideNavigationItems()
    }
}
Cristi Ghinea
  • 474
  • 1
  • 7
  • 20
  • Just an idea: WebView's scroll view already has a pan recognizer (webView.scrollView.panGestureRecognizer) so you could listen to this one (with addTarget) and disable bouncing on the scroll view. In this way you don't need to disable/enable the pan recognizer. – Darko Mar 03 '16 at 00:33
  • It worked! Thank you so much @Darko – Cristi Ghinea Mar 03 '16 at 10:56
  • You are welcome. I have added the comment as answer, please mark your question as answered. – Darko Mar 03 '16 at 11:36

2 Answers2

1

Thanks to @Darko: the idea was to use the panGesture property of the scroll view (also property of the web view).

private func gestures() {

    self.webView.scrollView.panGestureRecognizer.addTarget(
        self,
        action: "panGestureCaptured:"
    )
}

func panGestureCaptured(gesture: UIGestureRecognizer) {
    let touchPoint = gesture.locationInView(self.webView)

    print("touchPoint: \(touchPoint)")

    print("panGestureCaptured scrollView offset \(self.webView!.scrollView.contentOffset.y)")

    if self.webView!.scrollView.contentOffset.y == 0 {


        if self.webView!.scrollView.panGestureRecognizer.state == UIGestureRecognizerState.Changed {

            if touchPoint.y < self.webView!.frame.height * 0.3 {
                self.spinnerTopLayoutConstraint?.constant = touchPoint.y
            } else {
                self.spinnerTopLayoutConstraint?.constant = self.webView!.frame.height * 0.3
            }

        } else if self.webView!.scrollView.panGestureRecognizer.state == UIGestureRecognizerState.Ended {
            self.spinnerTopLayoutConstraint?.constant = UIApplication.sharedApplication().statusBarFrame.height + 20
        }
    }
}
Cristi Ghinea
  • 474
  • 1
  • 7
  • 20
1

WebView's scroll view already has a pan recognizer (webView.scrollView.panGestureRecognizer) so you could listen to this one (with addTarget) and disable bouncing on the scroll view. In this way you don't need to disable/enable the pan recognizer.

Darko
  • 9,655
  • 9
  • 36
  • 48