2014-08-28 2 views
32

Я ищу способ отключить жест увеличения «щепотку увеличения» в реализации IOS WKWebView. Существует свойство BOOL для увеличения, доступное для OS X, но похоже, что оно не доступно на iOS.Отключить жест увеличения в WKWebView

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, добавляя дочерний вид, чтобы захватить жест щепотки и т. Д.), Но я всегда обнаружил, что они вводят лаг в событие и хотят сохраните реализацию как можно чистую/взломанную, насколько это возможно.

ответ

59

Вы можете запретить пользователям масштабирование путем установки делегата UIScrollView вашего WKWebKit и реализации 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 
    } 
} 
+13

Не забудьте добавить соответствие 'UIScrollViewDelegate', установите' webView.scrollView.delegate = self; 'и смените указатель делегата на' deinit'. –

+2

Это следует отметить как правильный ответ. Родное решение для iOS вместо того, чтобы пытаться ввести JS. – C6Silver

+5

Я не согласен. Хотя собственное решение было бы идеальным, я думаю, что это решение столь же хакерское, как и JS, и, возможно, более хрупкое. Хотя WKWebView поддерживает UIScrollView, внутренне использует WKScrollView.Хотя это подкласс UIScrollView, он игнорирует/переопределяет много стандартного поведения (contentInset для одного). Масштабирование HTML-документа очень отличается от масштабирования UIView, поэтому я мог видеть будущее, когда это изменяется или больше не работает. Поскольку решение JS использует стандарты W3C, оно всегда должно поддерживаться. – Kevin

23

Нижеприведенный ответ больше не работает в бета-версии iOS 10.

Для повышения доступности на веб-сайты в Safari, пользователи теперь могут пинч-на-зум, даже если веб-сайт устанавливает пользователь масштабируемый = нет в просмотра.


WKWebView кажется уважать видовой экран мета-тег, так же, как 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 выполняется.

+6

Это все еще позволяет масштабировать двойное нажатие. 'minimum-scale = 1.0' необходимо установить, чтобы избежать этого. – fabb

+1

Этот ответ помог, но я все еще могу создать ситуации, в которых можно масштабировать. Не уверен, что и как еще. – gravitron

+0

Это правильный ответ - не связывайтесь с делегатом UIScrollView WKWebView. – thefaj

3

Swift 2,0

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

Обратите внимание, что это сделало бы это для всех WKWebViews – Luke

+0

Нет, если вы сначала подклассифицируете его и примените расширение к подклассу. Работает на меня. – BaseZen

1

у меня нет достаточно репутации, чтобы добавлять комментарии к ответам, но я хотел упомянуть, что решение Кевина (meta viewport) больше не работает в бета-версии iOS 10. Решение Landschaft работает для меня, хотя!

Поскольку решение JS использует стандарты W3C, оно всегда должно поддерживаться.

Ах, Кевин, я бы хотел, чтобы это было так.

Подробнее здесь: https://stackoverflow.com/a/37859168/1389714

+1

Welp. Так оно и есть, я полагаю. Изменение правильного ответа, спасибо за комментирование. – Kevin

0

Если это не так важно для вас, чтобы обрабатывать ссылки внутри HTML (скажем, вы хотите, чтобы отобразить только текст) простейший бы отключить взаимодействие с пользователем webView.userInteractionEnabled = false

+0

Это отключит прокрутку url –

+0

Поэтому я написал: «Если вам не важно обрабатывать ссылки внутри html» – lvp

+0

Это отключит прокрутку! OP хочет отключить пинч для увеличения, но я предполагаю, что он хочет использовать веб-просмотр. – tanzolone

0

Нам нужно изменить вызов делегата со следующими сигнатурами в XCode 8:

override func viewForZooming (в scrollView: UIScrollView) -> UIView? { return nil }

-1

Приложение, в котором я работаю, должно быть увеличено с помощью 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; 
     } 
    } 
} 
11

Полный Swift 3/IOS 10 версия ответа Ланд в:

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; 
    } 
} 
3

I попытались установки minimumZoomScale и maximumZoomScale свойства UIScrollView в 1 или isMultipleTouchEnabled свойство UIView для false или возврата nil от вызова viewForZooming(in:) из UIScrollViewDelegate, но никто не работал. В моем случае, после нескольких проб и ошибок, следующие работы в моем случае [Проверены на прошивке 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 
    } 
} 
+0

Спасибо! Это именно то, чего я хочу. Принятый ответ не может работать для моего случая, потому что после возвращения 'nil' в делегате масштаб моей веб-страницы неверен. –

+0

Отлично! Используйте это, вы можете изменить рамку изображений через JS без какого-либо плохого эффекта. – guozqzzu

1

это, как я отключил зум для Swift3 контроллера представления для один-WebView-единственного приложения

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; 
    }  

} 
+0

Наконец-то! Человеку трудно отслеживать постоянные изменения Swift (почти все остальное в сети имеет функцию делегата, которая является «viewForZoomingInScrollView». Спасибо за это обновление до «viewForZooming» –

+0

@thefaj это решение работает отлично для меня, вот оно – godblessstrawberry

0

Если WebView пользователем только для чтения целей, то есть, только для отображения веб-контента использовать

webView.isUserInteractionEnabled = false

При этом жест увеличения не будет работать на нем.

1

Вы можете использовать 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 
    } 
} 
Смежные вопросы