web-dev-qa-db-fra.com

Comment désactiver le défilement entièrement dans un WKWebView?

Je sais que cela ressemble à une simple question, on peut simplement dire:

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

ou même

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

mais, bien qu’il évite d’analyser (dans le sens contentOffset) à l’intérieur de WKWebviewit non , il ne l’empêche pas de recevoir des événements de type mouvement panoramique comportant du défilement.

Ainsi, des articles comme ceux de Huffington Post, dans lesquels JavaScript est inclus, permettent de modifier automatiquement les articles lorsque l'utilisateur fait défiler l'écran à gauche ou à droite, présentent toujours ce comportement.

Comment puis-je empêcher cela?

13
apouche

Avant Swift 3

Vous pouvez simplement désactiver le défilement sur son scrollView implicite

webView.scrollView.scrollEnabled = false

Swift 3

webView.scrollView.isScrollEnabled = false
29
Borut Tomazin

Cela m'a pris du temps, mais j'ai trouvé un moyen de le faire.

J'ai dû supprimer un identificateur de geste privé dans une sous-vue privée de la variable WKWebView.

J'ai eu une catégorie sur WKWebView pour le faire:

@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

J'espère que cela aidera quelqu'un un jour.

6
apouche

Crédit et merci à apouche pour le code Obj-C. Au cas où quelqu'un aurait le même problème, voici la solution de travail adaptée à 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)
                }
            }
        }
    }
  }
}
4
alain.s

J'ai constaté que je devais rendre mon contrôleur de vue UIScrollViewDelegate puis ajouter cette fonction pour empêcher le défilement.

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

Voici une extension C # pour WKWebView basée sur la solution Swift d’Alain.s (basée sur la solution d’apouche) pour ceux d’entre nous qui utilisent Xamarin. J'utilise cela dans mon application.

Les différences notables sont que je vérifie si les vues secondaires existent avant la mise en boucle et au lieu de rechercher de manière dynamique un "WKContentView" (quelque chose dont je ne suis même pas sûr qu'il soit possible dans Xamarin). Je vérifie simplement si chaque vue secondaire possède des GestureRecognizers et les supprime. Cela désactivera évidemment tous les types de gestes, alors tenez-en compte si vous vous attendez à une interaction de l'utilisateur avec le contenu 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
Tarostar

enfin self.webView.scrollView.userInteractionEnabled = NO

0
user5694405

Voici une version de Swift si quelqu'un a toujours des problèmes avec ce problème

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)
                        }
                    }
                }
            }
        }
0
Saul Hamadani

Voici une version de 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
Alan Jay