現象:WebView 加載包含錨點鏈接(<a href="#C4">)的 HTML,首次點擊跳轉正常,二次點擊同一鏈接無反應。部分舊設備(Android 2.2)複現率高。
點擊錨點鏈接時,URL 變為 file:///android_asset/chapters.html#C4。WebView 內部認為「文檔未變、僅片段識別符變化」,**攔截導航請求**,不觸發重載,導致 JS 滾動邏輯不再執行。
webView.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_UP) {
webView.reload(); // 每次點擊強制重載
}
return false;
});
缺點:閃屏、丟失滾動位置、性能差。
webView.setWebViewClient(new WebViewClient() {
private boolean isAnchorNavigation = false;
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("#")) {
isAnchorNavigation = true;
}
return false; // 允許 WebView 處理
}
@Override
public void onPageFinished(WebView view, String url) {
if (isAnchorNavigation) {
isAnchorNavigation = false;
// 強制重載同一 URL 觸發錨點跳轉
view.loadUrl(url);
}
}
});
在 HTML 中注入:
<script>
window.addEventListener('hashchange', function() {
var id = location.hash.substring(1);
var el = document.getElementById(id) || document.querySelector('a[name="' + id + '"]');
if (el) el.scrollIntoView();
});
</script>
優點:無需重載、體驗流暢、符合 Web 標準。
Android 4.4+ (Chromium WebView) 已修復此問題。若必須支持 2.2,建議嵌入 Crosswalk (已停止維護) 或引導用戶升級系統。
| 方案 | 優點 | 缺點 |
|---|---|---|
| reload() | 代碼極少 | 閃屏、狀態丟失 |
| WebViewClient 重載 | 可控、兼容舊版 | 仍有重載開銷 |
| JS hashchange | 零重載、體驗最佳 | 需修改 HTML/注入 JS |
優先採用 JS hashchange 方案,從根源解決錨點導航問題。