Отключить усиление в WKWebView
Я ищу способ отключить жест увеличения "щепотку для увеличения" в реализации IOS WKWebView. Существует свойство BOOL для увеличения, доступное для OS X, но похоже, что оно не доступно на iOS.
WKWebView.h
#if !TARGET_OS_IPHONE
/* @abstract A Boolean value indicating whether magnify gestures will
change the web view 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, добавляя дочерний вид, чтобы захватить жест щепотки и т.д.), но я всегда обнаружил, что они вводят лаг в событие и хотят сохранить реализация как чистая/взломанная, насколько это возможно.
Ответы
Ответ 1
Вы можете запретить пользователям масштабирование, установив делегат вашего WKWebKit UIScrollView и реализовав viewForZooming(in:)
как 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
}
}
Ответ 2
Следующий ответ больше не работает в бета-версии iOS 10.
Чтобы улучшить доступность веб-сайтов в Safari, пользователи теперь могут сжимать до масштабирования, даже если веб-сайт устанавливает масштабируемость пользователя = нет в окна просмотра.
WKWebView, похоже, уважает метатег viewport так же, как делает Mobile Safari (как и следовало ожидать). Итак, я обнаружил, что этот тег в DOM через javascript после загрузки страницы делает трюк. Я бы устал от этого решения, если вы точно не знаете, какой 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.
Ответ 3
Я попытался установить свойства minimumZoomScale
и maximumZoomScale
свойств UIScrollView
to 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
}
}
Ответ 4
Нативные решения не помогли мне, и инъекция JS не идеальна. Я заметил, что когда происходит масштабирование и вызывается мой делегат, pinchGestureRecognizer включается, хотя я отключил его при инициализации веб-просмотра. Чтобы это исправить, я устанавливаю его отключенным при каждом увеличении:
extension ViewController: UIScrollViewDelegate {
// disable zooming in webview
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
scrollView.pinchGestureRecognizer?.isEnabled = false
}
}
Ответ 5
Полная версия 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;
}
}
Ответ 6
Полный рабочий код для отключения масштабирования в WkWebView в Swift.
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)
}
}
Ответ 7
Вы можете использовать UIScrollViewDelegate для этого. Сначала назначьте делегировать свой веб-просмотр в viewDidLoad() или любой другой подходящий метод, например:
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
В случае, если вы отображаете локальный HTML, вы можете просто изменить этот HTML и поместить этот метатег в свой HTML:
<head>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
</head>
Ответ 9
Swift 2.0
extension WKWebView {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return nil
}
}
Ответ 10
это то, как я отключил масштабирование для контроллера 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;
}
}
Ответ 11
У меня недостаточно репутации для добавления комментариев к ответам, но я хотел бы упомянуть, что решение Kevin (meta viewport) больше не работает в бета-версии iOS 10. Решение Landschaft работает для меня, хотя!
Поскольку решение JS использует стандарты W3C, оно всегда должно поддерживаться.
А, Кевин, я бы хотел, чтобы это было так.
Подробнее здесь: fooobar.com/questions/29668/...
Ответ 12
Если вам не важно обрабатывать ссылки внутри html (скажем, вы хотите отображать только текст), самым простым было бы отключить взаимодействие с пользователем
webView.userInteractionEnabled = false
Ответ 13
Отключите двойное нажатие, чтобы увеличить жест, если требуется сбой распознавателя жестов. Это предотвратит действие браузера, когда пользователь дважды нажмет.
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())
}
Ответ 14
Простой способ предотвратить масштабирование
override func viewDidLoad() {
super.viewDidLoad()
webView.scrollView.delegate = self
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
scrollView.setZoomScale(1.0, animated: false)
}
Ответ 15
Нам нужно изменить вызов делегата со следующими сигнатурами в XCode 8:
override func viewForZooming (в scrollView: UIScrollView) → UIView? { return nil
}
Ответ 16
Если веб-просмотр является пользователем для целей только для чтения, то есть для отображения веб-контента используйте
webView.isUserInteractionEnabled = false
При этом жест увеличения не будет работать на нем.
Ответ 17
Вот слегка измененная версия ответа Гульшана Кумара, которая работала для меня в iOS 12.1.2, и она также предотвращает масштабирование из-за двойного нажатия и поворота. В моем примере я просто внедряю скрипт прямо в веб-представление. Я настроил масштаб до 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)
Ответ 18
Если лучше отключить масштабирование Pinch по окончании загрузки веб-страницы, а также можно указать, какой конкретный URL будет отключен
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if let url = webView.url, url.absoluteString == "***" {
webView.scrollView.pinchGestureRecognizer?.isEnabled = false
}
print("finish")
}
Ответ 19
В приложении, над которым я работаю, необходимо, чтобы представление было увеличено с помощью Javascript. Принятый ответ заблокировал масштабирование JavaScript изнутри страницы.
Мне нужно было отключить жест щепотки пользователем приложения. Единственное решение, которое я нашел, - отключить жест веб-представления после загрузки страницы:
- (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;
}
}
}
Ответ 20
Это сработало для меня. 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)