apouche
apouche

Reputation: 9983

How to disable scrolling entirely in a WKWebView?

I know this looks like a simple question one can simply say:

webview.scrollView.scrollEnabled = NO;
webview.scrollView.panGestureRecognizer.enabled = NO;
webview.scrollView.bounces = NO;

or even

for (UIView* subview in webview.subviews) {
  if ([subview respondsToSelector:@selector(setScrollEnabled:)]) {
      [(id)subview setScrollEnabled:enabled];
  }

  if ([subview respondsToSelector:@selector(panGestureRecognizer)]) {
      [[(id)subview panGestureRecognizer] setEnabled:enabled];
  }
}

but while it does prevent scolling (in the contentOffset meaning) inside the WKWebviewit doesn't prevent it from receiving pan gesture events involving scrolling.

So articles like those of the Huffington Post, which have javascript included to automatically change articles when the user scrolls left or right still get that behavior.

How can I prevent this ?

Upvotes: 36

Views: 35217

Answers (10)

Joey
Joey

Reputation: 2978

Swift 5

disableScrollView(self.webView)

func disableScrollView(_ view: UIView) {
    (view as? UIScrollView)?.isScrollEnabled = false
    view.subviews.forEach { disableScrollView($0) }
}

Upvotes: 0

Borut
Borut

Reputation: 8138

Before Swift 3

You can simply disable scroll on its implicit scrollView

webView.scrollView.scrollEnabled = false

Swift 3

webView.scrollView.isScrollEnabled = false

Upvotes: 58

Tarostar
Tarostar

Reputation: 1316

Here is a C# extension for WKWebView based on alain.s's swift solution (based on apouche's solution) for those of us using Xamarin. I am using this in my app.

Notable differences is that I check if subviews exist before looping and instead of dynamically looking for a "WKContentView" (something I'm not sure is even possible in Xamarin) I simply check if each subview has GestureRecognizers and remove them. This will obviously disable all types of gestures so consider this if you expect any user interaction with the web content.

public static class WKWebViewExtension
    {
        public static void DisableScroll(this WebKit.WKWebView webView)
        {
            webView.ScrollView.ScrollEnabled = false;
            webView.ScrollView.PanGestureRecognizer.Enabled = false;
            webView.ScrollView.Bounces = false;

            if (webView.Subviews != null)
            {
                foreach (var subView in webView.Subviews)
                {
                    if (subView is UIScrollView)
                    {
                        UIScrollView subScrollView = (UIScrollView)subView;

                        subScrollView.ScrollEnabled = false;
                        subScrollView.Bounces = false;
                        subScrollView.PanGestureRecognizer.Enabled = false;
                    }

                    if (subView.Subviews != null)
                    {
                        foreach (var subScrollView in subView.Subviews)
                        {
                            if (subScrollView.GestureRecognizers != null)
                            {
                                foreach (var gesture in subScrollView.GestureRecognizers)
                                {
                                    subScrollView.RemoveGestureRecognizer(gesture);
                                }
                            }
                        }
                    }


                }
            }
        }
    }

Upvotes: 1

user747594
user747594

Reputation: 151

I found that I had to make my view controller a UIScrollViewDelegate then add this function to prevent scrolling.

func scrollViewDidScroll(_ scrollView: UIScrollView) {
   scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}

Upvotes: 1

Alan Jay
Alan Jay

Reputation: 151

Here is a Swift 3 version:

extension WKWebView {

    func setScrollEnabled(enabled: Bool) {
        self.scrollView.isScrollEnabled = enabled
        self.scrollView.panGestureRecognizer.isEnabled = enabled
        self.scrollView.bounces = enabled

        for subview in self.subviews {
            if let subview = subview as? UIScrollView {
                subview.isScrollEnabled = enabled
                subview.bounces = enabled
                subview.panGestureRecognizer.isEnabled = enabled
            }

            for subScrollView in subview.subviews {
                if type(of: subScrollView) == NSClassFromString("WKContentView")! {
                    for gesture in subScrollView.gestureRecognizers! {
                        subScrollView.removeGestureRecognizer(gesture)
                    }
                }
            }
        }
    }
}

Upvotes: 1

user5694405
user5694405

Reputation: 29

finally self.webView.scrollView.userInteractionEnabled = NO

Upvotes: 2

Alain Stulz
Alain Stulz

Reputation: 744

Credit and many thanks to apouche for the Obj-C code. In case anybody else has the same problem, here is the working solution adapted for Swift 2

extension WKWebView {

  func setScrollEnabled(enabled: Bool) {
    self.scrollView.scrollEnabled = enabled
    self.scrollView.panGestureRecognizer.enabled = enabled
    self.scrollView.bounces = enabled

    for subview in self.subviews {
        if let subview = subview as? UIScrollView {
            subview.scrollEnabled = enabled
            subview.bounces = enabled
            subview.panGestureRecognizer.enabled = enabled
        }

        for subScrollView in subview.subviews {
            if subScrollView.dynamicType == NSClassFromString("WKContentView")! {
                for gesture in subScrollView.gestureRecognizers! {
                    subScrollView.removeGestureRecognizer(gesture)
                }
            }
        }
    }
  }
}

Upvotes: 5

Saul Hamadani
Saul Hamadani

Reputation: 16

Here's a swift version if anyone's still having trouble with this issue

let subviews = self.theWebView.scrollView.subviews
   for subview in subviews{
      if(subview.isKindOfClass(NSClassFromString("WKContentView"))){
                if let recognizers = subview.gestureRecognizers {
                    for recognizer in recognizers! {
                        if recognizer.isKindOfClass(NSClassFromString("UIWebTouchEventsGestureRecognizer")){
                           subview.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
                        }
                    }
                }
            }
        }

Upvotes: 0

apouche
apouche

Reputation: 9983

Took me a while but I figured out a way of doing this.

I had to remove a private gesture recognizer within a private subview of the WKWebView.

I had a category on WKWebView to do so:

@implementation WKWebView (Scrolling)

- (void)setScrollEnabled:(BOOL)enabled {
    self.scrollView.scrollEnabled = enabled;
    self.scrollView.panGestureRecognizer.enabled = enabled;
    self.scrollView.bounces = enabled;

    // There is one subview as of iOS 8.1 of class WKScrollView
    for (UIView* subview in self.subviews) {
        if ([subview respondsToSelector:@selector(setScrollEnabled:)]) {
            [(id)subview setScrollEnabled:enabled];
        }

        if ([subview respondsToSelector:@selector(setBounces:)]) {
            [(id)subview setBounces:enabled];
        }

        if ([subview respondsToSelector:@selector(panGestureRecognizer)]) {
            [[(id)subview panGestureRecognizer] setEnabled:enabled];
        }

        // here comes the tricky part, desabling
        for (UIView* subScrollView in subview.subviews) {
            if ([subScrollView isKindOfClass:NSClassFromString(@"WKContentView")]) {
                for (id gesture in [subScrollView gestureRecognizers]) {
                    if ([gesture isKindOfClass:NSClassFromString(@"UIWebTouchEventsGestureRecognizer")])
                        [subScrollView removeGestureRecognizer:gesture];
                }
            }
        }
    }

}


@end

Hope this helps anyone some day.

Upvotes: 6

3CC
3CC

Reputation: 502

Try to disable scrollView zoom in this way:

CGFloat zoomScale = webview.scrollView.zoomScale;
webview.scrollView.maximumZoomScale = zoomScale;
webview.scrollView.minimumZoomScale = zoomScale;

Upvotes: -1

Related Questions