Android WebView下拉刷新与SwipeRefreshLayout事件冲突解决

xiaoxiao2021-02-28  85

简介

本篇介绍WebView下拉刷新方法,另外解决SwipeRefreshLayout与WebView嵌套布局时滑动事件冲突的解决办法。

效果

下拉刷新

SwipeRefreshLayout控件可以优雅的完成下拉事件监听。 1、布局文件:

<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_fresh" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1"> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null" android:scrollbars="none" /> </android.support.v4.widget.SwipeRefreshLayout>

2、Activity

@BindView(R.id.swipe_fresh) SwipeRefreshLayout refreshLayout; @BindView(R.id.webview) WebView webView; ... private void initView() { refreshLayout.setColorSchemeResources(R.color.colorPrimary); refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { webView.loadUrl(url); } }); } ...

即在SwipeRefreshLayout控件的refresh事件中重新加载WebView的内容就可以了。

事件冲突

完成了上述功能后,会发现网页无法上拉,往上滑动就会触发下拉刷新控件的refresh事件。演示:

解决冲突

关于两个控件的冲突问题,网络上有不少解决办法,有的是自定义SwipeRefreshLayout重写onTouchEvent方法;有的是重写WebView的scroll监听。

最后我找到一个比较好的解决办法。 将Activity代码修改为

@BindView(R.id.swipe_fresh) SwipeRefreshLayout refreshLayout; @BindView(R.id.webview) WebView webView; ... private void initView() { refreshLayout.setColorSchemeResources(R.color.colorPrimary); refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { webView.loadUrl(url); } }); // 设置子视图是否允许滚动到顶部 refreshLayout.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() { @Override public boolean canChildScrollUp(SwipeRefreshLayout parent, @Nullable View child) { return webView.getScrollY() > 0; } }); } ...

说明:canChildScrollUp方法返回的true/false表示子视图是否可返回顶部,我们改成webView.getScrollY() > 0后表示webView到顶部时返回false,refreshLayout可接收到下拉动作,触发refresh事件。 此时上拉、下拉都没问题了,看下效果

源码分析

/** * Set a callback to override {@link SwipeRefreshLayout#canChildScrollUp()} method. Non-null * callback will return the value provided by the callback and ignore all internal logic. * @param callback Callback that should be called when canChildScrollUp() is called. */ public void setOnChildScrollUpCallback(@Nullable OnChildScrollUpCallback callback) { mChildScrollUpCallback = callback; }

setOnChildScrollUpCallback方法可以设置一定监听接口,返回子视图是否可以滑动到顶部。

/** * Classes that wish to override {@link SwipeRefreshLayout#canChildScrollUp()} method * behavior should implement this interface. */ public interface OnChildScrollUpCallback { /** * Callback that will be called when {@link SwipeRefreshLayout#canChildScrollUp()} method * is called to allow the implementer to override its behavior. * * @param parent SwipeRefreshLayout that this callback is overriding. * @param child The child view of SwipeRefreshLayout. * * @return Whether it is possible for the child view of parent layout to scroll up. */ boolean canChildScrollUp(SwipeRefreshLayout parent, @Nullable View child); }

OnChildScrollUpCallback 接口就一个canChildScrollUp方法,返回是否可滚动。

在上述实现过程中,我们判断WebView的状态:

在顶部时,返回false,表示子视图不可滚动,refreshLayout接收到滑动事件,引出滑动视图和调用滑动刷新方法;不在顶部时,webView.getScrollY() > 0,返回true,表示子视图可滚动,refreshLayout中canChildScrollUp()返回true,刷新控件不再处理滑动问题,所以没有调用滑动刷新方法。

参考资料

http://blog.csdn.net/u012461368/article/details/51037573

转载请注明原文地址: https://www.6miu.com/read-81186.html

最新回复(0)