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

Coordinator Layout Behavior失效:WebView滚动Toolbar显隐功能未实现

解决WebView配合CoordinatorLayout滚动隐藏Toolbar失效的问题

看起来你已经搭好了基础结构,但WebView的滚动事件默认不会被AppBarLayout.ScrollingViewBehavior正确识别,再加上SwipeRefreshLayout的包裹,容易出现事件拦截的情况,咱们一步步来修复:

第一步:确认XML结构的正确性

先把你的XML结构补全并修正关键点:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

这里要确保:

  • AppBarLayout直接作为CoordinatorLayout的子视图
  • SwipeRefreshLayout正确设置了app:layout_behavior="@string/appbar_scrolling_view_behavior"
  • Toolbar的scrollFlags确实是scroll|enterAlways

第二步:让WebView的滚动事件被CoordinatorLayout感知

WebView的滚动是内部实现的,默认不会把滚动事件传递给外层的ScrollingViewBehavior,所以我们需要手动把滚动事件传递给AppBarLayout的Behavior:

方案一:API 23+ 直接用原生WebView监听

如果你的最低适配版本是API 23及以上,直接给WebView设置滚动监听即可:

WebView webView = findViewById(R.id.webview);
AppBarLayout appBarLayout = findViewById(R.id.appbar);
CoordinatorLayout coordinator = findViewById(R.id.coordinator);

webView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    
    if (behavior != null) {
        // 计算滚动差值,传递给Behavior处理
        int dy = scrollY - oldScrollY;
        behavior.onNestedPreScroll(coordinator, appBarLayout, v, 0, dy, new int[2], 0);
    }
});

方案二:兼容低版本的自定义WebView

如果需要适配API 23以下的版本,自定义一个能暴露滚动事件的WebView:

public class ObservableWebView extends WebView {
    private OnScrollChangeListener mScrollListener;

    public ObservableWebView(Context context) {
        super(context);
    }

    public ObservableWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ObservableWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mScrollListener != null) {
            mScrollListener.onScrollChange(this, l, t, oldl, oldt);
        }
    }

    public void setOnScrollChangeListener(OnScrollChangeListener listener) {
        mScrollListener = listener;
    }

    public interface OnScrollChangeListener {
        void onScrollChange(WebView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
    }
}

然后替换XML里的WebView,再设置监听:

ObservableWebView webView = findViewById(R.id.webview);
// 后续监听代码和方案一一致,把WebView换成ObservableWebView即可

第三步:处理SwipeRefreshLayout的事件冲突

有时候SwipeRefreshLayout会拦截顶部的滚动事件,导致WebView的滚动监听没触发,这时候可以设置一个回调,只有当WebView滚动到顶部时才允许下拉刷新:

SwipeRefreshLayout swipeRefresh = findViewById(R.id.swipe_refresh);
swipeRefresh.setOnChildScrollUpCallback((parent, child) -> {
    // 当WebView没有滚动到顶部时,拦截SwipeRefreshLayout的下拉事件
    return webView.getScrollY() > 0;
});

这样调整之后,WebView向上滚动时Toolbar就会隐藏,向下滚动时会重新显示啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:38:35