You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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);
    }
}

方案说明

  1. 定义OnLayoutChangeListener,在WebView布局发生变化时触发,此时WebView的布局已稳定,调用scrollTo可以精准恢复到之前的位置。
  2. 在onHideCustomView中添加该监听,替代原有的postDelayed代码。
  3. 恢复滚动位置后立即移除监听,避免后续布局变化时重复触发。

这种方案不需要依赖固定延迟时间,能适配不同设备的布局渲染速度,比延迟方案更可靠、更符合主流浏览器的实现逻辑。

内容的提问来源于stack exchange,提问作者Krylatov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:40:22