ViewPager2嵌套NestedScrollView中WebView加载多Twitter iframe时收缩异常
解决NestedScrollView+双WebView+ViewPager2布局中WebView收缩问题
针对你在ViewPager2的Fragment中使用NestedScrollView嵌套两个WebView(中间插入广告)时出现的WebView加载后收缩、内容显示不全(尤其含Twitter iframe时)的问题,可通过以下步骤解决:
1. 基础布局优化
调整NestedScrollView属性
确保NestedScrollView开启fillViewport,让内部内容能正确填充视口:
<androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <!-- 内部垂直布局:WebView1 + 广告容器 + WebView2 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <WebView android:id="@+id/web_view1" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/ad_container" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="16dp" /> <WebView android:id="@+id/web_view2" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.core.widget.NestedScrollView>
禁用WebView自身滚动
避免WebView的滚动逻辑和NestedScrollView的滚动冲突,同时防止WebView因自身滚动导致高度异常:
WebView webView1 = findViewById(R.id.web_view1); WebView webView2 = findViewById(R.id.web_view2); // 隐藏滚动条 webView1.setVerticalScrollBarEnabled(false); webView1.setHorizontalScrollBarEnabled(false); webView2.setVerticalScrollBarEnabled(false); webView2.setHorizontalScrollBarEnabled(false); // 禁用触摸滚动事件 webView1.setOnTouchListener((v, event) -> true); webView2.setOnTouchListener((v, event) -> true);
2. 动态计算WebView高度(适配动态内容/iframe)
WebView的onPageFinished仅触发主文档加载完成,像Twitter iframe这类异步加载的内容不会触发该回调,因此需要通过JS监听内容高度变化:
启用JS并注入监听脚本
// 开启JavaScript支持 webView1.getSettings().setJavaScriptEnabled(true); webView2.getSettings().setJavaScriptEnabled(true); // 定义JS交互接口,用于接收内容高度更新通知 class WebViewHeightCallback { @JavascriptInterface public void onHeightChanged(int height) { requireActivity().runOnUiThread(() -> { // 更新当前WebView的高度 if (webView1.isAttachedToWindow()) { ViewGroup.LayoutParams params = webView1.getLayoutParams(); params.height = height; webView1.setLayoutParams(params); } else if (webView2.isAttachedToWindow()) { ViewGroup.LayoutParams params = webView2.getLayoutParams(); params.height = height; webView2.setLayoutParams(params); } }); } } // 给WebView绑定JS接口 webView1.addJavascriptInterface(new WebViewHeightCallback(), "HeightCallback"); webView2.addJavascriptInterface(new WebViewHeightCallback(), "HeightCallback"); // 注入监听脚本:监听主文档及所有iframe加载完成后的高度变化 String heightMonitorJs = "function updateHeight() { " + " HeightCallback.onHeightChanged(document.body.scrollHeight); " + "} " + "window.onload = updateHeight; " + "var iframes = document.getElementsByTagName('iframe'); " + "for(var i=0; i<iframes.length; i++) { " + " iframes[i].onload = updateHeight; " + "}"; // 在WebView加载完成后注入脚本 webView1.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.loadUrl("javascript:" + heightMonitorJs); } }); webView2.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); view.loadUrl("javascript:" + heightMonitorJs); } });
3. 优化ViewPager2页面切换时的布局重绘
ViewPager2默认预加载相邻页面,导致Fragment在后台时WebView高度计算异常,可在Fragment的onResume中重新触发高度计算:
@Override public void onResume() { super.onResume(); // 重新计算两个WebView的高度 refreshWebViewHeight(webView1); refreshWebViewHeight(webView2); } private void refreshWebViewHeight(WebView webView) { if (webView != null && webView.getSettings().getJavaScriptEnabled()) { webView.evaluateJavascript("document.body.scrollHeight", heightStr -> { try { int height = Integer.parseInt(heightStr.replace("\"", "")); ViewGroup.LayoutParams params = webView.getLayoutParams(); params.height = height; webView.setLayoutParams(params); } catch (NumberFormatException e) { e.printStackTrace(); } }); } }
4. 特殊情况处理:Twitter iframe显示异常
如果仍存在Twitter iframe导致的高度问题,可尝试禁用WebView硬件加速(部分机型硬件加速会导致iframe布局异常):
webView1.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webView2.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
内容的提问来源于stack exchange,提问作者Garvi Shah
相关产品推荐
相关产品推荐

