如何在WKWebView中完全禁用滚动?

32

我知道这看起来像一个简单的问题,有人可能会直接回答:

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

甚至

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

虽然它可以防止在WKWebview中滚动(在contentOffset的意义上),但它并不会防止其接收涉及滚动的平移手势事件。

因此,像Huffington Post这样的文章,其中包含JavaScript以在用户向左或向右滚动时自动更改文章仍会出现该行为。

我该如何预防这种情况?

10个回答

56

在 Swift 3 之前

你可以简单地在它的隐式 scrollView 上禁用滚动。

webView.scrollView.scrollEnabled = false

Swift 3

webView.scrollView.isScrollEnabled = false

8
在Swift 3中,以下代码对我有效:webView.scrollView.isScrollEnabled = false - Jonathan
14
我喜欢你可能甚至没有读过我的原始问题。 - apouche

6

花了我一些时间,但我找到了一种方法来做到这一点。

我必须删除WKWebView的私有子视图中的一个私有手势识别器。

我在WKWebView上有一个类别可以这样做:

@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

希望这能在某一天对任何人有所帮助。


5

感谢apouche提供的Obj-C代码。如果有其他人遇到同样的问题,这里是适用于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)
                }
            }
        }
    }
  }
}

2

最终,self.webView.scrollView.userInteractionEnabled = NO。


4
它还能防止触摸事件例如点击。 - Etienne Martin

1
我发现必须将我的视图控制器设置为 UIScrollViewDelegate,然后添加此函数以防止滚动。
func scrollViewDidScroll(_ scrollView: UIScrollView) {
   scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: false)
}

1
这是一份针对WKWebView的C#扩展,基于alain.s的Swift解决方案(基于apouche的解决方案),适用于使用Xamarin的用户。我在我的应用程序中使用它。
值得注意的区别是,在循环之前,我会检查子视图是否存在,而不是动态查找“WKContentView”(我甚至不确定在Xamarin中是否可能),我只需检查每个子视图是否具有GestureRecognizers并将其删除。这显然会禁用所有类型的手势,因此请考虑这一点,如果您期望与Web内容进行任何用户交互。
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);
                                }
                            }
                        }
                    }


                }
            }
        }
    }

1
这是一个Swift 3版本:

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)
                    }
                }
            }
        }
    }
}

0

Swift 5

disableScrollView(self.webView)

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

0

如果还有人遇到这个问题,这里是一个 Swift 版本的解决方案

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)
                        }
                    }
                }
            }
        }

-1
尝试以这种方式禁用scrollView缩放:
CGFloat zoomScale = webview.scrollView.zoomScale;
webview.scrollView.maximumZoomScale = zoomScale;
webview.scrollView.minimumZoomScale = zoomScale;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接