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

引言

SwipeRefreshLayout是Android在Support.v4包中为我们提供的用户刷新UI的一个组件,大部分场景下我们会使用它包裹RecyclerView,在列表上下拖动到顶部时继续向下滑动视图触发刷新事件,我们可以通过给SwipeRefreshLayout设置OnRefreshListener通过回调方法onRefresh()来完成下拉刷新事件的监听动作。但是当我们把WebView作为子View放置在SwipeRefreshLayout中时,H5上的scroll事件与原生安卓的滑动事件就会出现冲突,导致我们无法完成预期的效果,下面看下出现问题的效果图,然后我们一起解决下这个原生跟H5上的滑动冲突,从而达到我们最终的效果。

问题效果图
滑动冲突效果图

从图上我们可以很清楚的看到,当我们在滑动H5页的时候,H5页向下滑动的过程中我们如果向上拖动页面,会同时触发先触发SwipeRefreshLayout上的监听事件,导致H5页无法正常向上拖动,但是此时并非我们的预期,我们看下存在滑动冲突事件的代码

存在冲突的代码

@RequiresApi(api = Build.VERSION_CODES.ECLAIR_MR1)
    @Override
    protected void setUpView() {
        wvPage = findViewById(R.id.wv_page);
        swipeRefreshLayout = findViewById(R.id.srl_refresh);
        wvPage.getSettings().setJavaScriptEnabled(true);
        wvPage.getSettings().setDomStorageEnabled(true);
        wvPage.setWebViewClient(new WebViewClient());
        wvPage.setWebChromeClient(new WebChromeClient());
        wvPage.loadUrl(getUrl());

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                swipeRefreshLayout.setRefreshing(false);
                wvPage.reload();
            }
        });

      ...  //省略部分代码
    }

在上面我们已经提到了出现滑动冲突是由于H5内部的scroll事件与SwipeRefreshLayout滑动监听发生了冲突,我们只需要找到解决此二者冲突的解决方案,问题就可以迎刃而解。

阅读SwipeRefreshLayout的源码,我们发现这样一段回调接口

/**
  * 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在Y轴方向的滚动距离来判断当前webview加载的H5页是否在顶部来决定SwipeRefreshLayout的回调刷新方法是否被触发。

总结如下:

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

解决后的效果图
解决滑动冲突效果图

代码

  @RequiresApi(api = Build.VERSION_CODES.ECLAIR_MR1)
    @Override
    protected void setUpView() {
        wvPage = findViewById(R.id.wv_page);
        swipeRefreshLayout = findViewById(R.id.srl_refresh);
        wvPage.getSettings().setJavaScriptEnabled(true);
        wvPage.getSettings().setDomStorageEnabled(true);
        wvPage.setWebViewClient(new WebViewClient());
        wvPage.setWebChromeClient(new WebChromeClient());
        wvPage.loadUrl(getUrl());

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                swipeRefreshLayout.setRefreshing(false);
                wvPage.reload();
            }
        });

        swipeRefreshLayout.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() {
            @Override
            public boolean canChildScrollUp(@NonNull SwipeRefreshLayout swipeRefreshLayout, @Nullable View view) {
                return wvPage.getScrollY() > 0;  // 原生安卓使用getScrollY()来判断在Y轴的距离
//                return wvPage.getWebScrollY() > 0;   // 我项目中使用的X5内核的webview需要调用getWebScrollY()来判断在Y轴的距离
            }
        });
    }
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: 在WebView中实现下拉刷新,可以通过以下步骤: 1. 在布局文件中添加SwipeRefreshLayout控件,并将WebView作为其子视图。 ``` <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> ``` 2. 在Activity或Fragment中,获取SwipeRefreshLayoutWebView的实例,并为SwipeRefreshLayout设置下拉刷新监听器。 ``` SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipe_refresh); WebView webView = findViewById(R.id.web_view); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { webView.reload(); } }); ``` 3. 在WebViewWebViewClient中,重写onPageFinished方法,当页面加载完成时,停止SwipeRefreshLayout的刷新动画。 ``` webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); swipeRefreshLayout.setRefreshing(false); } }); ``` 这样,当用户下拉SwipeRefreshLayout时,会触发onRefresh方法,从而重新加载WebView中的页面,并在页面加载完毕后停止刷新动画。 ### 回答2: WebView 下拉刷新是在使用 WebView 控件时,实现下拉刷新页面内容的功能。下拉刷新通常用于在 WebView 中加载新的内容或更新已有的内容。 实现 WebView 下拉刷新的一种常见方式是使用下拉刷新控件,例如 SwipeRefreshLayout。这个控件可以包裹 WebView,并且在用户下拉 WebView 时触发刷新操作。具体代码如下: 首先,在 XML 布局文件中将 WebView 包裹在 SwipeRefreshLayout 中: ```xml <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout" 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" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> ``` 然后,在 Java 代码中设置下拉刷新的监听器,并在刷新时重新加载 WebView 内容: ```java SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout); WebView webView = findViewById(R.id.webView); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { webView.reload(); // 刷新 WebView 内容 swipeRefreshLayout.setRefreshing(false); // 停止刷新动画 } }); ``` 以上代码中,`swipeRefreshLayout.setOnRefreshListener` 方法用于设置下拉刷新的监听器,当用户下拉时,会回调 `onRefresh` 方法。在这个方法中,我们通过 `webView.reload()` 方法重新加载 WebView 内容,之后调用 `swipeRefreshLayout.setRefreshing(false)` 方法停止刷新动画。 通过以上的步骤,我们就可以在 WebView 中实现下拉刷新的功能了。用户在 WebView 上下拉时,会触发刷新动画,并在刷新时重新加载 WebView 内容,使用户能够获取最新的页面内容。 ### 回答3: 在WebView中实现下拉刷新可以通过结合SwipeRefreshLayoutWebView来实现。 首先,在布局文件中添加SwipeRefreshLayout布局和WebView布局,如下所示: ```xml <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/refresh_layout" 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" /> </android.support.v4.widget.SwipeRefreshLayout> ``` 然后,在代码中找到SwipeRefreshLayoutWebView的实例,并设置下拉刷新监听器和WebView的WebChromeClient,如下所示: ```java SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.refresh_layout); final WebView webView = findViewById(R.id.webview); // 设置下拉刷新监听器 swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 在这里执行刷新操作,比如重新加载网页 webView.reload(); } }); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { // 在页面加载完成后停止刷新 if (newProgress == 100) { swipeRefreshLayout.setRefreshing(false); } } }); ``` 在下拉刷新监听器中,可以执行刷新操作,比如重新加载网页。当WebView加载完成后,通过setRefreshing(false)停止刷新。 这样,用户在WebView界面中下拉屏幕时,就能触发下拉刷新操作,并重新加载WebView中的网页内容。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值