WKWebView - предотвращает автоматическую прокрутку c, вызванную выделением текста пользователем - PullRequest
8 голосов
/ 05 марта 2020

Когда пользователь выполняет жест касания и удержания, чтобы выбрать слово, а затем перетаскивает свой палец к верхнему или нижнему краям экрана, страница автоматически прокручивается, чтобы удовлетворить выбор.

вот короткий клип, демонстрирующий это

Я бы хотел предотвратить это поведение внутри WKWebView.

Вот что я пробовал до сих пор:

в файле bridge.js, который доступен для веб-просмотра:

var shouldAllowScrolling = true;

document.addEventListener('selectionchange', e => {
    shouldAllowScrolling = getSelectedText().length === 0;
    window.webkit.messageHandlers.selectionChangeHandler.postMessage(
        {
            shouldAllowScrolling: shouldAllowScrolling
        });
    console.log('allow scrolling = ', shouldAllowScrolling);
});

, а затем в реализации WKScriptMessageHandler:

public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage)
    {
        switch message.name
        {
        case "selectionChangeHandler":
            let params = paramsDictionary(fromMessageBody: message.body)
            let shouldEnableScrolling = params["shouldAllowScrolling"] as? Bool ?? true
            cell?.webView.scrollView.isScrollEnabled = shouldEnableScrolling
            cell?.webView.scrollView.isUserInteractionEnabled = shouldEnableScrolling // not together with the line above 
        default:
            fatalError("\(#function): received undefined message handler name: \(message.name)")
        }
    }

Аналогичным образом я попытался вызвать * Функция 1020 * работает непосредственно в файле javascript для нескольких событий, а именно scroll и touchmove, например так:

document.addEventListener('touchmove', e => {
    if (!shouldAllowScrolling) {
        e.preventDefault()
    }
}, {passive: false});

оба метода успешно предотвращают прокрутку при выделении некоторого текста, но не отвергни поведение, описанное в самом верху моего вопроса.

Я могу принимать решения либо в Swift, либо в JavaScript, либо в комбинации обоих.

1 Ответ

5 голосов
/ 08 марта 2020

В итоге я решил эту проблему, сохранив последнюю позицию прокрутки и прокрутив ее до нужного места, например:

var shouldAllowScrolling = true;
var lastSavedScrollLeft = 0;
var lastSavedScrollTop = 0;

function saveScrollPosition() {
    lastSavedScrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
    lastSavedScrollTop = window.pageYOffset || document.documentElement.scrollTop;
}

document.addEventListener('touchstart', e => {
    saveScrollPosition();
});

document.addEventListener('touchend', () => {
    // enable scrolling when the user lifts their finger, to allow scrolling while text selection is still present
    shouldAllowScrolling = true;
});

document.addEventListener('scroll', e => {
    if (!shouldAllowScrolling) {
        window.scrollTo(lastSavedScrollLeft, lastSavedScrollTop);
    }
});

document.addEventListener('selectionchange', e => {
    shouldAllowScrolling = getSelectedText().length === 0;
});

Если кто-то может предложить более элегантное решение, которое полностью предотвращает прокрутку, будьте счастливы принять его.

РЕДАКТИРОВАТЬ:

это решение может вызвать легкое встряхивание / дрожание.

, что можно решить, выполнив прокрутку непосредственно через WKWebView вместо вызова window.scrollTo() в javascript.

...