在WKWebView中禁用放大手势

Kev*_*vin 56 webkit ios ios8 wkwebview

我正在寻找一种方法来禁用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;
Run Code Online (Sandbox Code Playgroud)

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

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

Lan*_*aft 76

您可以通过设置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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记在`UIScrollViewDelegate`中添加一致性,设置`webView.scrollView.delegate = self;`并使`deinit`中的委托指针无效. (14认同)
  • 我不同意.虽然本机解决方案是理想的,但我认为这个解决方案和JS一样,并且可能更脆弱.当WKWebView出售UIScrollView时,内部使用WKScrollView.虽然它是UIScrollView的子类,但它忽略/覆盖了许多标准行为(contentInset for one).缩放HTML文档与缩放UIView非常不同,因此我可以看到未来这种变化/不再有效.由于JS解决方案使用W3C标准,因此应始终支持它. (6认同)
  • 这应该被称为正确的答案.本机iOS解决方案,而不是尝试注入JS. (2认同)
  • @Prcela 取消委托是没有必要的。这是一个弱变量,因此不会创建保留循环。 (2认同)

Kev*_*vin 43

以下答案不再适用于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];
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这仍然允许双击缩放.需要设置`minimum-scale = 1.0`以避免这种情况. (10认同)

小智 34

我曾尝试设置minimumZoomScalemaximumZoomScale属性UIScrollView1isMultipleTouchEnabled财产UIViewfalse或返回nil援引viewForZooming(in:)UIScrollViewDelegate,但没有奏效.在我的情况下,经过几次试验和错误,以下工作在我的情况下[在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
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 双击缩放仍然有效. (5认同)

pul*_*ife 17

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

extension ViewController: UIScrollViewDelegate {

    // disable zooming in webview
    func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
        scrollView.pinchGestureRecognizer?.isEnabled = false
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是 /sf/answers/3024378941/ 的精确副本,比这个早一年发布。为什么? (2认同)

Sim*_*amp 14

完整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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Gul*_*mar 13

完成工作代码以禁用swift中的WkWebView缩放

导入UIKit导入WebKit

class ViewController:UIViewController,WKUIDelegate {

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    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()

        let myUrl = URL(string: "https://www.google.com")

        let myRequest = URLRequest(url: myUrl!)
        webView.load(myRequest)
    }
}
Run Code Online (Sandbox Code Playgroud)

}


Les*_*ary 8

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

<head>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
</head>
Run Code Online (Sandbox Code Playgroud)


Yak*_* Ad 5

您可以为此使用UIScrollViewDelegate。首先在viewDidLoad()或任何其他合适的方法中将委托分配给您的Web视图:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个解决方案对于iOS13来说是一个很好的起点!我唯一缺少的是在 HTML 中设置 `&lt;meta name="viewport" content="width=device-width, initial-scale=1, Maximum-scale=1"/&gt;` 因为当手机旋转时已更改,应用程序内的视图正在缩放。 (2认同)