Android中WebView设置overflow:auto上滑触发SwipeRefreshLayout刷新问题
解决WebView在SwipeRefreshLayout中上滑触发刷新的问题
这个问题我之前做项目的时候也碰到过,简直头疼!核心原因是SwipeRefreshLayout默认的滑动判断逻辑太“霸道”了——它不管WebView内部有没有滚动空间,只要检测到上滑手势就会触发刷新,完全没给WebView处理内部滚动的机会。
解决方案:自定义SwipeRefreshLayout,优化滚动判断逻辑
我们需要重写SwipeRefreshLayout的canChildScrollUp()方法,让它只有在WebView确实滑到顶部、没有更多内部滚动空间的时候,才允许触发刷新操作。
1. 创建自定义SwipeRefreshLayout类
public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { private WebView mTargetWebView; public CustomSwipeRefreshLayout(Context context) { super(context); } public CustomSwipeRefreshLayout(Context context, AttributeSet attrs) { super(context, attrs); } // 传入需要判断的WebView实例 public void setTargetWebView(WebView webView) { mTargetWebView = webView; } @Override public boolean canChildScrollUp() { if (mTargetWebView == null) { return super.canChildScrollUp(); } // 判断WebView是否还有向上滚动的空间: // 1. WebView的滚动距离大于0(说明已经滚过一段,还能往上滑回到顶部) // 2. WebView内容总高度 * 缩放比例 > WebView自身高度(说明内容超过了视图高度,还有更多内容可以滚动) boolean canScroll = mTargetWebView.getScrollY() > 0; float contentHeight = mTargetWebView.getContentHeight() * mTargetWebView.getScale(); boolean hasMoreContent = contentHeight > mTargetWebView.getMeasuredHeight(); return canScroll || hasMoreContent; } }
2. 修改布局文件,替换为自定义的SwipeRefreshLayout
<com.your.app.package.CustomSwipeRefreshLayout android:id="@+id/swiperefresh" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </com.your.app.package.CustomSwipeRefreshLayout>
注意把com.your.app.package替换成你自己的项目包名。
3. 在代码中关联WebView和自定义SwipeRefreshLayout
在你的Activity或者Fragment里,初始化时把WebView传给自定义布局:
CustomSwipeRefreshLayout swipeRefresh = findViewById(R.id.swiperefresh); WebView webView = findViewById(R.id.webview); // 关联WebView,让自定义布局能判断滚动状态 swipeRefresh.setTargetWebView(webView); // 正常设置WebView的其他属性,比如开启JS、设置滚动样式等 webView.getSettings().setJavaScriptEnabled(true); webView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
额外注意点
- 如果WebView的内容是动态加载的(比如通过JS渲染),建议在
WebViewClient的onPageFinished回调里重新触发一次滚动判断,避免内容加载前判断不准确的问题。 - 如果你用的是AndroidX的
SwipeRefreshLayout,只需要把导入的包换成androidx.swiperefreshlayout.widget.SwipeRefreshLayout即可,代码逻辑完全一样。
内容的提问来源于stack exchange,提问作者Sali Manaf
相关产品推荐
相关产品推荐

