如何解决WebView退出全屏视频后自动滚动至页面顶部问题?
解决WebView退出视频全屏后自动滚动到顶部的优化方案
问题背景
通过onShowCustomView实现WebView视频全屏播放功能,但退出全屏模式后,WebView会自动滚动至页面顶部。使用positionY记录退出前的滚动位置,再通过延迟调用webView.scrollTo(0, positionY)的方式暂时解决了问题,但这种依赖固定延迟的方案不够优雅,希望找到更可靠的实现方式。
优化方案:监听WebView布局变化恢复滚动位置
问题的核心是退出全屏时,WebView的布局尚未完成,直接调用scrollTo无法生效。我们可以通过监听WebView的布局变化事件,在布局完成后精准恢复滚动位置,替代固定延迟的方案。
修改后的代码实现
private class MyChrome extends WebChromeClient{ private View mCustomView; private WebChromeClient.CustomViewCallback mCustomViewCallback; private int mOriginalOrientation; private int mOriginalSystemUiVisibility; private int positionY; private final View.OnLayoutChangeListener layoutChangeListener = new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { // 布局变化后恢复滚动位置 webView.scrollTo(0, positionY); // 移除监听,避免重复触发 webView.removeOnLayoutChangeListener(this); } }; MyChrome() {} public Bitmap getDefaultVideoPoster(){ if (mCustomView == null){ return null; } return BitmapFactory.decodeResource(getApplicationContext().getResources(), 2130837573); } public void onHideCustomView(){ ((FrameLayout)getWindow().getDecorView()).removeView(this.mCustomView); this.mCustomView = null; getWindow().getDecorView().setSystemUiVisibility(this.mOriginalSystemUiVisibility); setRequestedOrientation(this.mOriginalOrientation); this.mCustomViewCallback.onCustomViewHidden(); this.mCustomViewCallback = null; // 添加布局变化监听,替代延迟方案 webView.addOnLayoutChangeListener(layoutChangeListener); } public void onShowCustomView(View paramView, WebChromeClient.CustomViewCallback paramCustomViewCallback){ if (this.mCustomView != null){ onHideCustomView(); return; } positionY = webView.getScrollY(); this.mCustomView = paramView; this.mOriginalSystemUiVisibility = getWindow().getDecorView().getSystemUiVisibility(); this.mOriginalOrientation = getRequestedOrientation(); this.mCustomViewCallback = paramCustomViewCallback; ((FrameLayout)getWindow().getDecorView()).addView(this.mCustomView, new FrameLayout.LayoutParams(-1, -1)); getWindow().getDecorView().setSystemUiVisibility(3846 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); } }
方案说明
- 定义
OnLayoutChangeListener,在WebView布局发生变化时触发,此时WebView的布局已稳定,调用scrollTo可以精准恢复到之前的位置。 - 在
onHideCustomView中添加该监听,替代原有的postDelayed代码。 - 恢复滚动位置后立即移除监听,避免后续布局变化时重复触发。
这种方案不需要依赖固定延迟时间,能适配不同设备的布局渲染速度,比延迟方案更可靠、更符合主流浏览器的实现逻辑。
内容的提问来源于stack exchange,提问作者Krylatov
相关产品推荐
相关产品推荐

