佈局結構:ScrollView → ViewPager (3 個 Fragment) → WebView。需在 WebView 載入完成後立即取得內容高度 (getContentHeight() * getScale()),並設定給 ViewPager,但該方法必須在使用者觸摸 WebView 後才回傳正確值。
WebView.getContentHeight() 依賴 WebKit 排版引擎完成佈局,而排版通常在 首次繪製/觸摸觸發 後才完成。在 `onPageFinished` 回調中呼叫仍可能回傳 0。
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 內部排版狀態。
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 內部自行滾動,放棄「完美貼合」需求,換取實作簡單度。
NestedScrollView + ViewPager2 (支援巢狀滾動)。Chrome Custom Tabs、GeckoView) 或原生化渲染。