You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView findNext()点击屏幕后跳转位置异常求助

Fixing WebView findNext() Jump Issue After Clicking WebView

Hey there! I totally get your frustration with this WebView search behavior—native Android WebView's findAllAsync() and findNext() can be tricky when users interact with the WebView content. Let's break down why this happens and how to fix it.

Why This Happens

The native WebView search methods (findAllAsync()/findNext()) rely on an internal search session that gets reset when you tap anywhere on the WebView. This reset makes findNext() start searching from the tapped position instead of continuing the original sequence. Disabling touch or clearing focus doesn't help because the session reset happens deep in WebView's internal logic when it registers a tap event.

Solution: Custom Search & Highlight with JavaScript

The most reliable fix is to take full control of the search and navigation using JavaScript. This way, you maintain the search state independently, so WebView taps won't disrupt the sequence. Here's how to implement it:

Step 1: Enable JavaScript in WebView

First, make sure JavaScript is enabled in your WebView settings:

webView.getSettings().setJavaScriptEnabled(true);

Step 2: Inject JavaScript Functions

Add these JavaScript functions to handle search, highlighting, and navigation. You can inject them when the WebView finishes loading your HTML:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        // Inject JS code
        String jsCode = """
            // Clear existing highlights and reset state
            let currentMatchIndex = -1;
            let totalMatches = 0;

            function searchAndHighlight(text) {
                // Remove old highlights
                document.querySelectorAll('.highlight, .current-highlight').forEach(el => {
                    el.replaceWith(document.createTextNode(el.textContent));
                });

                if (!text.trim()) {
                    totalMatches = 0;
                    currentMatchIndex = -1;
                    return;
                }

                // Find all matches
                const regex = new RegExp(text, 'gi');
                const body = document.body;
                const matches = [];
                let match;
                const bodyHtml = body.innerHTML;
                
                while ((match = regex.exec(bodyHtml)) !== null) {
                    matches.push({ start: match.index, length: match[0].length });
                }

                totalMatches = matches.length;
                currentMatchIndex = -1;

                // Highlight all matches (reverse to avoid index shifting)
                let newHtml = bodyHtml;
                matches.reverse().forEach(match => {
                    const start = match.start;
                    const end = start + match.length;
                    newHtml = newHtml.substring(0, start) + 
                        '<span class="highlight">' + newHtml.substring(start, end) + '</span>' + 
                        newHtml.substring(end);
                });

                body.innerHTML = newHtml;
            }

            function goToNextMatch() {
                if (totalMatches === 0) return;
                
                // Update previous current highlight
                const prevCurrent = document.querySelector('.current-highlight');
                if (prevCurrent) {
                    prevCurrent.classList.remove('current-highlight');
                    prevCurrent.classList.add('highlight');
                }

                // Move to next match (loop back to start if at end)
                currentMatchIndex = (currentMatchIndex + 1) % totalMatches;

                // Highlight current match and scroll to it
                const highlights = document.querySelectorAll('.highlight');
                const current = highlights[currentMatchIndex];
                current.classList.remove('highlight');
                current.classList.add('current-highlight');
                current.scrollIntoView({ behavior: 'smooth', block: 'center' });
            }
        """;
        view.evaluateJavascript(jsCode, null);

        // Inject CSS for highlights
        String css = """
            const style = document.createElement('style');
            style.textContent = `
                .highlight { background-color: yellow; }
                .current-highlight { background-color: red; }
            `;
            document.head.appendChild(style);
        """;
        view.evaluateJavascript(css, null);
    }
});

Step 3: Update Your Button Click Listeners

Replace your existing search and next button logic with calls to the JavaScript functions:

Search Button

searchButton.setOnClickListener(v -> {
    String searchText = et.getText().toString().trim();
    // Escape special characters to avoid JS syntax errors
    String escapedText = searchText.replace("'", "\\'").replace("\"", "\\\"");
    webView.evaluateJavascript("searchAndHighlight('" + escapedText + "')", null);
});

Next Button

next.setOnClickListener(v -> {
    webView.evaluateJavascript("goToNextMatch()", null);
});

Key Benefits of This Approach

  • Full Control: You maintain the search state (currentMatchIndex, totalMatches) independently, so WebView taps won't reset it.
  • Customizable: You can easily tweak highlight colors, scroll behavior, or add a "previous" button with minimal changes.
  • User-Friendly: Users can still interact with the WebView (tap links, scroll, zoom) without breaking the search sequence.

Note on Special Characters

Make sure to escape special characters in the search text (like quotes) to avoid JavaScript syntax errors. The example above includes basic escaping, but you can expand it for more edge cases if needed.

内容的提问来源于stack exchange,提问作者sara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:57:44