首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android WebView 在 ScrollView+ViewPager 嵌套中無法提前獲取內容高度的替代方案

     編輯:程式設計綜合問答

問題場景

佈局結構:ScrollView → ViewPager (3 個 Fragment) → WebView。需在 WebView 載入完成後立即取得內容高度 (getContentHeight() * getScale()),並設定給 ViewPager,但該方法必須在使用者觸摸 WebView 後才回傳正確值。

根本限制

WebView.getContentHeight() 依賴 WebKit 排版引擎完成佈局,而排版通常在 首次繪製/觸摸觸發 後才完成。在 `onPageFinished` 回調中呼叫仍可能回傳 0。

替代方案 (按推薦順序)

方案一:JavaScript 注入回傳高度 (最穩定)


webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        view.evaluateJavascript(
            "(function() { return document.body.scrollHeight; })();",
            value -> {
                int height = Integer.parseInt(value.replace("\"", ""));
                // 在主執行緒更新 ViewPager 高度
                view.post(() -> updatePagerHeight(height));
            }
        );
    }
});

原理:JS 直接讀取 `document.body.scrollHeight`,不依賴 WebView 內部排版狀態。

方案二:自訂 WebView 監聽 onSizeChanged


public class ObservableWebView extends WebView {
    private OnSizeChangedListener listener;
    public ObservableWebView(Context context) { super(context); }
    public void setOnSizeChangedListener(OnSizeChangedListener l) { listener = l; }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (listener != null) listener.onSizeChanged(w, h);
    }
    public interface OnSizeChangedListener { void onSizeChanged(int w, int h); }
}

在 `onSizeChanged` 回調中取得高度並更新 ViewPager。需確保 WebView 已完成排版 (通常在載入完成後會觸發一次)。

方案三:固定高度 / 最大高度 + 滾動內部

若內容高度可預估 (如文章頁),直接給 ViewPager 固定高度 (如 `match_parent` 或 `1000dp`),讓 WebView 內部自行滾動,放棄「完美貼合」需求,換取實作簡單度。

方案四:放棄 ScrollView + ViewPager + WebView 嵌套

  • 改用 NestedScrollView + ViewPager2 (支援巢狀滾動)。
  • 或將 WebView 內容改為原生 `TextView` + `ImageView` (透過 Jsoup 解析 HTML),徹底避開 WebView 高度難題。

總結建議

  1. 優先採用 **JS 注入方案**,相容性最好,程式碼量少。
  2. 若專案已大量使用 WebView,考慮引入 **WebView 替代庫** (如 Chrome Custom Tabs、GeckoView) 或原生化渲染。
  3. 避免 `ScrollView` 直接包裹 `ViewPager` 包裹 `WebView`,此結構在 Android 官方文件中明確不建議。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved