web-dev-qa-db-ja.com

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に渡す、ピンチジェスチャーをキャプチャするために子ビューを追加する、など)。可能な限りクリーン/ハックします。

54
Kevin

次のように、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
    }
}
74
Landschaft

以下の回答は、iOS 10ベータ版では機能しなくなりました。

SafariのWebサイトのアクセシビリティを向上させるために、Webサイトがビューポートでuser-scalable = noを設定している場合でも、ピンチしてズームできるようになりました。


WKWebViewは、Mobile Safariと同じように(予想どおり)ビューポートメタタグを尊重しているようです。そのため、ページの読み込みが成功した後、JavaScriptを介してそのタグをDOMに挿入することがわかりました。どのHTMLがwebviewにロードされているかを正確に知らない限り、このソリューションにうんざりするでしょう。さもないと、意図しない結果になると思います。私の場合、HTML文字列を読み込んでいるので、アプリに同梱されているHTMLに追加するだけです。

任意のWebページに対して一般的に行うには:

- (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を実行する必要があるのは新しいページだけなので、完了したナビゲーションの種類を確認するのが賢明かもしれません。

42
Kevin

minimumZoomScalemaximumZoomScaleおよびUIScrollViewプロパティを_1_に設定するか、isMultipleTouchEnabledUIViewプロパティをfalseに設定するか、nilviewForZooming(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
   }
}
_
30
yohannes

ネイティブソリューションは私にとっては機能していませんでした。JSの注入は理想的ではありません。ズームが発生してデリゲートが呼び出されると、webviewの初期化時に無効にしたにもかかわらず、pinchGestureRecognizerが有効になっていることに気付きました。これを修正するために、ズームが開始されるたびに無効に設定しました:

extension ViewController: UIScrollViewDelegate {

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

完全Swift 3/iOS 1 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
Simon Epskamp

SwiftのWkWebViewでズームを無効にするための作業コードを完成させます。

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)
    }
}
11
Gulshan Kumar

これには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
  }
}
4
Yakup Ad

ローカルhtmlを表示する場合は、このhtmlを変更して、このメタタグをHTMLに配置するだけです。

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

Swift 2.

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

これがSwiftのビューコントローラーを無効にする方法です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;
    }    

}
2

ズームを防ぐ簡単な方法

override func viewDidLoad() {
    super.viewDidLoad()

    webView.scrollView.delegate = self
}

func scrollViewDidZoom(_ scrollView: UIScrollView) {

    scrollView.setZoomScale(1.0, animated: false)
}
1
Waqar Ahmed

HTML内のリンクを処理することが重要でない場合(テキストのみを表示する場合など)、最も簡単な方法はユーザーの操作をオフにすることですwebView.userInteractionEnabled = false

1
lvp

ジェスチャー認識の失敗を要求することにより、ダブルタップを無効にしてジェスチャーをズームします。これにより、ユーザーがダブルタップしたときにブラウザーがアクションを実行できなくなります。

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

回答にコメントを追加するほどの評判はありませんが、ケビンのソリューション(メタビューポート)はiOS 10ベータ版では動作しなくなったことに言及したかったのです。しかし、Landschaftのソリューションは私のために働いています!

JSソリューションはW3C標準を使用するため、常にサポートする必要があります。

ああ、ケビン、これらのことがどのように機能したかを願っています。

詳細はこちら: https://stackoverflow.com/a/37859168/1389714

1
mark

これは 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)
0
Scott Gardner

ウェブページの読み込みが完了したときにピンチズームを無効にする方が良い場合は、どの特定のURLを無効にするかを指定することもできます。

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

    print("finish")
} 
0
Jin

XCode 8では、次の署名を使用してデリゲート呼び出しを変更する必要があります。

func viewForZooming(scrollView:UIScrollView)-> UIView?をオーバーライドしますか? {nilを返す}

0
Brianster

WebViewが読み取り専用、つまりWebコンテンツを表示するだけのユーザーの場合

webView.isUserInteractionEnabled = false

これにより、ズームジェスチャは機能しません。

0
Sameer Bhide