在WKWebView中禁用放大手势

时间:2014-08-28 16:31:15

标签: ios webkit 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;

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

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

20 个答案:

答案 0 :(得分:73)

您可以通过设置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
    }
}

答案 1 :(得分:41)

以下答案在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。

答案 2 :(得分:26)

我尝试将minimumZoomScale的{​​{1}}和maximumZoomScale属性设置为UIScrollView1属性isMultipleTouchEnabledUIView或者返回false来调用nil的{​​{1}}但没有效果。在我的情况下,经过多次试验和错误,以下工作在我的情况下[在iOS 10.3上测试]:

viewForZooming(in:)

答案 3 :(得分:16)

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

extension ViewController: UIScrollViewDelegate {

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

答案 4 :(得分: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;
    }
}

答案 5 :(得分:10)

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

导入UIKit 导入WebKit

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

}

}

答案 6 :(得分:4)

如果您显示本地html,则只需修改此html并将此meta标记放入html中即可。

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

答案 7 :(得分: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
  }
}

答案 8 :(得分:3)

Swift 2.0

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

答案 9 :(得分:2)

这是我为一个仅限webview的应用

禁用 Swift3 视图控制器的缩放方式
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;
    }    

}

答案 10 :(得分:1)

防止缩放的简单方法

override func viewDidLoad() {
    super.viewDidLoad()

    webView.scrollView.delegate = self
}

func scrollViewDidZoom(_ scrollView: UIScrollView) {

    scrollView.setZoomScale(1.0, animated: false)
}

答案 11 :(得分:1)

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

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

答案 12 :(得分:1)

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

答案 13 :(得分:1)

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

  

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

啊,凯文,我希望这些是有用的。

更多信息:https://stackoverflow.com/a/37859168/1389714

答案 14 :(得分:0)

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

webView.isUserInteractionEnabled = false

通过这种缩放手势不会对它起作用。

答案 15 :(得分:0)

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

覆盖func viewForZooming(在scrollView中:UIScrollView) - &gt; UIView的? {         返回零 }

答案 16 :(得分:0)

这是Gulshan Kumar的答案的稍作修改的版本,在iOS 12.1.2中对我有用,并且还可以防止由于双击和旋转而导致缩放。在我的示例中,我只是将脚本直接注入到Web视图中。我将比例调整为60%,并且不需要使用串联来构建源字符串。

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)

答案 17 :(得分: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")
} 

答案 18 :(得分:-1)

这对我有用。 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)

答案 19 :(得分:-1)

我工作的应用程序需要通过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;
        }
    }
}