我正在寻找一种方法来禁用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,添加子视图以捕获捏手势等)但我总是发现那些引入滞后的事件并希望将实现保持为尽可能清洁/黑客。
您可以通过设置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
}
}
这就是我为一个仅限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;
}
}
我没有足够的声誉来为答案添加评论,但我想提一下凯文的解决方案(元视口)不再适用于iOS 10测试版。不过,Landschaft的解决方案对我有用!
由于JS解决方案使用W3C标准,因此应始终支持它。
啊,凯文,我希望这些东西能起作用。
如果你在html中处理链接并不重要(假设你只想显示文本),最简单的方法是关闭用户交互webView.userInteractionEnabled = false
通过要求手势识别器失败,禁用双击以缩放手势。当用户双击时,它将阻止浏览器执行操作。
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())
}
一种防止缩放的简单方法
override func viewDidLoad() {
super.viewDidLoad()
webView.scrollView.delegate = self
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
scrollView.setZoomScale(1.0, animated: false)
}
我们需要在XCode 8中使用以下签名更改委托调用:
覆盖func viewForZooming(在scrollView:UIScrollView中) - > UIView? {return nil}
如果webview是用户的只读目的,即仅用于显示Web内容的使用
webView.isUserInteractionEnabled = false
这样,缩放手势将无法使用。
这是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)
如果最好在网页完成加载时禁用缩放缩放,并且还可以指定要禁用的特定URL
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if let url = webView.url, url.absoluteString == "***" {
webView.scrollView.pinchGestureRecognizer?.isEnabled = false
}
print("finish")
}
我工作的应用程序需要通过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;
}
}
}
以下答案不再适用于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。
这对我有用。 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)
我已经尝试将minimumZoomScale
的maximumZoomScale
和UIScrollView
属性设置为1
的isMultipleTouchEnabled
或UIView
属性到false
或者从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
}
}
本机解决方案对我不起作用,注入JS并不理想。我注意到当发生缩放并调用我的委托时,即使我在初始化webview时禁用了pinchGestureRecognizer,也会启用它。要解决此问题,我会在缩放开始时将其设置为禁用:
extension ViewController: UIScrollViewDelegate {
// disable zooming in webview
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
完整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;
}
}
完成工作代码以禁用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)
}
}
您可以使用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
}
}
如果您显示本地html,您可以修改此html并将此元标记放入您的html:
<head>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
</head>
Swift 2.0
extension WKWebView {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return nil
}
}