SwipeRefreshLayout嵌套WebView无法向下滚动、误触发刷新及Odoo适配问题
问题根源
你遇到的冲突核心是SwipeRefreshLayout的下拉手势和WebView滚动手势的判定逻辑不兼容,Odoo站点失效是因为Odoo前端采用内部独立div做滚动容器,WebView本身的scrollY始终为0,导致你原来的滚动监听逻辑完全失效。
可直接生效的修复步骤
1. 修正现有代码的语法&逻辑错误
你修改后的代码存在三处基础错误,先修复:
onStart、onStop方法写在了onCreate方法内部,需移出到类的同级作用域- 重复添加了两次
OnScrollChangedListener,删掉多余的添加代码 - 滚动判定逻辑错误,
mWebView.getScrollY() == -1的判断无实际意义,替换为系统提供的滚动能力判定方法canScrollVertically
2. 自定义SwipeRefreshLayout适配WebView内部滚动
自定义SwipeRefreshLayout重写触摸拦截逻辑,直接判定WebView是否真的滚动到顶部,无需额外监听滚动事件:
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { private WebView mWebView; public CustomSwipeRefreshLayout(@NonNull Context context) { super(context); } public CustomSwipeRefreshLayout(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public void setWebView(WebView webView) { mWebView = webView; } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (mWebView != null && mWebView.canScrollVertically(-1)) { // WebView还能向上滚动,不拦截手势 return false; } return super.onInterceptTouchEvent(ev); } }
3. 修改布局文件
将布局中的androidx.swiperefreshlayout.widget.SwipeRefreshLayout替换为你自定义的CustomSwipeRefreshLayout(注意替换成你自己的完整包名):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- 替换为自定义的SwipeRefreshLayout --> <com.yourpackage.CustomSwipeRefreshLayout android:id="@+id/swipe" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/activity_main_webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </com.yourpackage.CustomSwipeRefreshLayout> </LinearLayout>
4. 调整Activity初始化逻辑
删除原来的滚动监听代码,在初始化时给自定义的刷新布局绑定WebView,同时补充Odoo站点必需的WebView配置:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = findViewById(R.id.activity_main_webview); swipeRefreshLayout = findViewById(R.id.swipe); // 绑定WebView到自定义刷新布局 swipeRefreshLayout.setWebView(mWebView); WebSettings webSettings = mWebView.getSettings(); webSettings.setJavaScriptEnabled(true); // Odoo站点必需的配置 webSettings.setDomStorageEnabled(true); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(true); mWebView.setWebViewClient(new MyWebViewClient()); mWebView.loadUrl("https://hkmu.comercio.co.id"); // 保留你原来的刷新逻辑即可,无需再做滚动监听 swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { swipeRefreshLayout.setRefreshing(true); new Handler().postDelayed(new Runnable() { @Override public void run() { swipeRefreshLayout.setRefreshing(false); mWebView.reload(); } }, 2000); } }); swipeRefreshLayout.setColorSchemeColors( getResources().getColor(android.R.color.holo_blue_dark), getResources().getColor(android.R.color.holo_orange_dark), getResources().getColor(android.R.color.holo_green_dark), getResources().getColor(android.R.color.holo_red_dark) ); }
极端场景适配
如果上述方案仍然失效,说明Odoo站点的滚动逻辑做了特殊处理,可通过JS注入的方式获取页面真实滚动状态:
- 给WebView添加JS接口,接收页面滚动状态
- 在
WebViewClient的onPageFinished方法中注入JS,监听页面滚动容器的滚动事件,滚动到顶部时通知原生端开启刷新,否则关闭。
内容的提问来源于stack exchange,提问作者Mangetsu
相关产品推荐
相关产品推荐

