WKWebView-ユーザーのテキスト選択によってトリガーされる自動スクロールを防止


8

ユーザーがタップアンドホールドジェスチャを実行して単語を選択し、指を画面の上端または下端のいずれかにドラッグすると、選択に対応するためにページが自動的にスクロールします。

ここにそれを示す短いクリップがあります

内でこの動作を防止したいと思いWKWebViewます。

これが私がこれまでに試したことです:

bridge.jsのWebViewにアクセス可能なファイル:

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

同様に、preventDefault()一連のイベント、つまりscrolland について、JavaScriptファイルで関数を直接呼び出してみましたtouchmove

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

どちらの方法でも、一部のテキストが選択されている場合はスクロールを回避できますが、質問の一番上に記載されている動作はオーバーライドしません。

SwiftとJavaScript、または両方の組み合わせのソリューションを受け入れることができます。

回答:


5

最後のスクロール位置を保存し、必要に応じてその位置までスクロールすることで、この問題を解決することができました。

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

誰かがスクロールを完全に妨げるよりエレガントなソリューションを提供できれば、それを受け入れて喜んでしまいます。

編集:

このソリューションは、軽い揺れ/ジッターを引き起こす可能性があります。

これは、JavaScriptでWKWebView呼び出すのwindow.scrollTo()ではなく、を通じてネイティブにスクロールを実行することで解決できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.