WKWebView-防止用户文本选择时自动滚动

9
当用户长按单词并将手指向屏幕顶部或底部拖动时,页面会自动滚动以适应所选内容。这是一个涉及IT技术的问题。以下是一段需要翻译的内容:

这里有一个演示它的简短视频。

我想在WKWebView中防止这种情况发生。

以下是我迄今为止尝试过的:

在可供Web视图访问的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)")
        }
    }

同样地,在JavaScript文件中尝试通过直接调用preventDefault()函数来阻止一些事件的发生,这些事件包括scrolltouchmove

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

两种方法都可以成功地防止当选中文本时出现滚动,但它们不能覆盖我问题顶部描述的行为。

我可以接受使用Swift和JavaScript或二者混合的解决方案。

1个回答

7

我最终通过保存最后的滚动位置,并在适当时候滚动到它来解决了这个问题,方法如下:

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

如果有人能提供一个更优雅的解决方案,完全防止滚动,我会很高兴接受。
编辑:
这个解决方案可能会导致轻微的晃动/抖动。
这可以通过在 shouldAllowScrolling 设置为 false 时本地禁用滚动来解决,如下所示:
webView.scrollView.isScrollEnabled = false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接