首页 文章

在WKWebView中禁用放大手势

提问于
浏览
47

我正在寻找一种方法来禁用WKWebView的iOS实现上的“捏缩放”放大手势 . OS X有一个放大BOOL属性,但它似乎在iOS上不可用 .

WKWebView.h

#if !TARGET_OS_IPHONE
/* @abstract A Boolean value indicating whether magnify gestures will
 change the web view's magnification.
 @discussion It is possible to set the magnification property even if
 allowsMagnification is set to NO.
 The default value is NO.
 */
@property (nonatomic) BOOL allowsMagnification;

我也试过看看WKWebView的手势识别器,但这似乎是一个空阵列 . 我假设实际的识别器在组件的结构中更深(比较复杂,看起来很复杂),如果可能的话,宁愿不去挖掘它们 .

我知道可能存在可能会禁用手势的黑客攻击(有选择地将手势传递给WebView,添加子视图以捕获捏手势等)但我总是发现那些引入滞后的事件并希望将实现保持为尽可能清洁/黑客 .

20 回答

  • 3

    我工作的应用程序需要通过Javascript缩放视图 . 接受的答案也阻止了JavaScript从页面内部进行缩放 . 我只需要禁用应用程序用户的捏合手势 . 我发现的唯一解决方案是在页面加载后禁用Web视图的手势:

    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
        /* disable pinch gesture recognizer to allow zooming the web view by code but prevent zooming it by the user */
        for (UIGestureRecognizer *gr in self.webView.scrollView.gestureRecognizers) {
            if ([gr isKindOfClass:[UIPinchGestureRecognizer class]]) {
                gr.enabled = NO;
            }
        }
    }
    
  • 1

    您可以通过设置WKWebKit的UIScrollView的委托并实现 viewForZooming(in:) 来阻止用户进行缩放,如下所示:

    class MyClass {
        let webView = WKWebView()
    
        init() {
            super.init()
            webView.scrollView.delegate = self
        }
    
        deinit() {
            // Without this, it'll crash when your MyClass instance is deinit'd
            webView.scrollView.delegate = nil
        }
    }
    
    extension MyClass: UIScrollViewDelegate {
        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return nil
        }
    }
    
  • 0

    以下答案不再适用于iOS 10测试版 .

    为了改善Safari网站的可访问性,即使网站在视口中设置了user-scalable = no,用户现在也可以进行缩放 .


    WKWebView似乎以与Mobile Safari相同的方式尊重视口元标记(如预期的那样) . 因此,我发现在页面加载完成后,通过javascript将该标记注入DOM . 除非你确切地知道HTML加载到webview中,否则我会厌倦这个解决方案,否则我怀疑它会产生意想不到的后果 . 就我而言,我正在加载HTML字符串,所以我可以将它添加到我随应用程序发布的HTML中 .

    要对任何网页进行一般性操作:

    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
        NSString *javascript = @"var meta = document.createElement('meta');meta.setAttribute('name', 'viewport');meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');document.getElementsByTagName('head')[0].appendChild(meta);";
    
        [webView evaluateJavaScript:javascript completionHandler:nil];
    }
    

    看看刚刚完成了什么样的导航可能是明智的,因为只有新页面需要执行这个javascript .

  • 70

    我已经尝试将 UIScrollViewminimumZoomScaleUIScrollView 属性设置为 UIViewUIViewisMultipleTouchEnabled 属性为 false 或者从调用 viewForZooming(in:) UIScrollViewDelegate 返回 nil 但没有效果 . 在我的情况下,经过几次试验和错误,以下工作在我的情况下[在iOS 10.3上测试]:

    class MyViewController: UIViewController {
       var webView: WKWebView?
    
       override viewDidLoad() {
          super.viewDidLoad()
    
          //...
          self.webView.scrollView.delegate = self
          //...
       }
    }
    
    extension MyViewController: UIScrollViewDelegate { 
       func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
          scrollView.pinchGestureRecognizer?.isEnabled = false
       }
    }
    
  • -1

    完整 Swift 3 / iOS 10 版本的Landschaft的回答:

    import UIKit
    import WebKit
    
    class MyViewController: UIViewController, UIScrollViewDelegate {
    
        var webView = WKWebView()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.addSubview(webView)
            webView.scrollView.delegate = self
        }
    
        // Disable zooming in webView
        func viewForZooming(in: UIScrollView) -> UIView? {
            return nil;
        }
    }
    
  • 14

    本机解决方案对我不起作用,注入JS并不理想 . 我注意到当发生缩放并调用我的委托时,即使我在初始化webview时禁用了pinchGestureRecognizer,也会启用它 . 要解决此问题,我会在缩放开始时将其设置为禁用:

    extension ViewController: UIScrollViewDelegate {
    
        // disable zooming in webview
        func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
            scrollView.pinchGestureRecognizer?.isEnabled = false
        }
    }
    
  • 13

    Complete working code to disable zooming in WkWebView in swift

    导入UIKit导入WebKit

    class ViewController:UIViewController,WKUIDelegate {

    // @IBOutlet var eventWkWebView: WKWebView!
    
    var webView : WKWebView!
    
    
    override func loadView() {
    
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration:webConfiguration)
        webView.uiDelegate = self
    
        let source: String = "var meta = document.createElement('meta');" +
            "meta.name = 'viewport';" +
            "meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
            "var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);";
    
        let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
        webView.configuration.userContentController.addUserScript(script)
    
        view = webView
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        //  view.addSubview(eventWkWebView)
    
    
        let myUrl = URL(string: "https://www.google.com")
    
        let myRequest = URLRequest(url: myUrl!)
        webView.load(myRequest)
    
    }
    

    }

  • 0

    如果您显示本地html,您可以修改此html并将此元标记放入您的html:

    <head>
    <meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
    </head>
    
  • 2

    Swift 2.0

    extension WKWebView {
        func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
            return nil
        }
    }
    
  • 4

    您可以使用UIScrollViewDelegate . 首先在viewDidLoad()或任何其他合适的方法中将委托分配给您的webview:

    class LoginViewController: UIViewController, WKUIDelegate, UIScrollViewDelegate {
      override func viewDidLoad() {
      webView.scrollView.delegate = self 
      }
    
     //And add this delegate method in your controller: 
    
      func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
      scrollView.pinchGestureRecognizer?.isEnabled = false
      scrollView.panGestureRecognizer.isEnabled = false
      }
    }
    
  • 22

    这是我为 one-webview-only app 视图控制器禁用缩放的方法 one-webview-only app

    import UIKit
    import WebKit
    
    class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate {
    
        @IBOutlet var webView: WKWebView!
    
        override func loadView() {
            webView = WKWebView()
            webView.navigationDelegate = self
            view = webView
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            webView.scrollView.delegate = self
        }
    
        func viewForZooming(in: UIScrollView) -> UIView? {
            return nil;
        }    
    
    }
    
  • -1

    我没有足够的声誉来为答案添加评论,但我想提一下凯文的解决方案(元视口)不再适用于iOS 10测试版 . 不过,Landschaft的解决方案对我有用!

    由于JS解决方案使用W3C标准,因此应始终支持它 .

    啊,凯文,我希望这些东西能起作用 .

    更多这里:https://stackoverflow.com/a/37859168/1389714

  • 1

    如果你在html中处理链接并不重要(假设你只想显示文本),最简单的方法是关闭用户交互 webView.userInteractionEnabled = false

  • 3

    通过要求手势识别器失败,禁用双击以缩放手势 . 当用户双击时,它将阻止浏览器执行操作 .

    import UIKit
    
    class DisableDoubleTapRecognizer : UITapGestureRecognizer, UIGestureRecognizerDelegate{
        override init(target: Any?, action: Selector?) {
            super.init(target: target, action: action)
        }
        
        init() {
            super.init(target:nil, action: nil)
            self.numberOfTapsRequired = 2;
            self.delegate = self;
        }
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
            return true;
        }
    }
    
    //in your view controller
    override func viewDidLoad() {
            super.viewDidLoad()
            
            webView.addGestureRecognizer(DisableDoubleTapRecognizer())
        }
    
  • 39

    我们需要在XCode 8中使用以下签名更改委托调用:

    覆盖func viewForZooming(在scrollView:UIScrollView中) - > UIView?

  • 0

    如果webview是用户的只读目的,即仅用于显示Web内容的使用

    webView.isUserInteractionEnabled = false

    这样,缩放手势将无法使用 .

  • 1

    这是Gulshan Kumar 's answer that worked for me in iOS 12.1.2, and it also prevents zooming due to double-taps and rotation. In my example, I just inject the script directly into the web view. I adjusted the scale to 60%, and there'的略微修改版本,无需在构建源字符串时使用连接 .

    let source = "var meta = document.createElement('meta'); meta.name = 'viewport'; meta.content = 'width=device-width, initial-scale=0.6, maximum-scale=0.6, user-scalable=no'; var head = document.getElementsByTagName('head')[0]; head.appendChild(meta);"
    
    let script = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
    
    webView.configuration.userContentController.addUserScript(script)
    
  • 0

    如果最好在网页完成加载时取消Pinch缩放,并且还可以指定要转到哪个特定URL被废弃

    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
         if let url = webView.url, url.absoluteString == "***" {                       
            webView.scrollView.pinchGestureRecognizer?.isEnabled = false
         }
    
        print("finish")
    }
    
  • 0

    一种防止缩放的简单方法

    override func viewDidLoad() {
        super.viewDidLoad()
    
        webView.scrollView.delegate = self
    }
    
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
    
        scrollView.setZoomScale(1.0, animated: false)
    }
    
  • 9

    这对我有用 . https://gist.github.com/paulofierro/5b642dcde5ee9e86a130

    let source: String = "var meta = document.createElement('meta');" +
      "meta.name = 'viewport';" +
      "meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no';" +
      "var head = document.getElementsByTagName('head')[0];" + "head.appendChild(meta);";
      let script: WKUserScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
      let userContentController: WKUserContentController = WKUserContentController()
      let conf = WKWebViewConfiguration()
      conf.userContentController = userContentController
      userContentController.addUserScript(script)
      let webView = WKWebView(frame: CGRect.zero, configuration: conf)
    

相关问题