【问题标题】:How to detect scrollend of webview in android?如何在android中检测webview的滚动端?
【发布时间】:2014-01-08 14:14:51
【问题描述】:

我的是一个原生应用程序,如果用户滚动到 webview 的末尾,我想在其中显示/隐藏一个按钮。我查看了一个答案here,并完全了解了如何通过接口注册回调。我的主要问题是我无法在 onScrollChanged 方法中进行计算。我已经尝试过 getHeight()、getContentHeight()、top 等的组合,但它似乎启动得太早了。我尝试了一个像谷歌这样内容相对较少的简单页面以及一个新闻页面。

这些逻辑适用于普通的滚动视图。由于网页内容很多,因此可能会弄乱计算。粘贴示例代码:不起作用。

@Override
protected void onScrollChanged(int left, int top, int oldLeft, int oldTop) {
    if ( mOnWebViewBottomReachedListener != null ) {
        //if ( (getContentHeight() - (top + getHeight())) <= mMinDistance )
        int diff = (getBottom() - (getHeight() + getScrollY()));
        Log.e("values ", diff+" o");
        if ((int) Math.floor(getContentHeight() * getScaleY()) == top)
            mOnWebViewBottomReachedListener.onBottomReached(this);
    }
    super.onScrollChanged(left, top, oldLeft, oldTop);
}

需要帮助。谢谢。

【问题讨论】:

标签: android webview


【解决方案1】:
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    int height = (int) Math.floor(this.getContentHeight() * this.getScale());  
    int webViewHeight = this.getMeasuredHeight();  
    if(this.getScrollY() + webViewHeight >= height){  
       Log.i("THE END", "reached");
    }
    super.onScrollChanged(l, t, oldl, oldt);
}

此逻辑适用于 webview。

【讨论】:

  • 不错的尝试。但不是完美的,因为当新页面刚刚加载时,网络视图会提供旧网页的 getContentHeight()。
  • 刚刚通过 newScale 更改了 this.getScale() 并在 onScaleChanged 方法中获取 newScale。在developer.android.com/reference/android/webkit/… 中查看更多详细信息
  • 当我将 getScale()(deprecated) 更改为 getScaleY() 时为我工作。我试图检测滚动到底部。
【解决方案2】:

经过大量谷歌搜索后,我找到的所有解决方案都是计算高度和确定 scrollOfset,但在大多数情况下,它们中的大多数都不可靠,导致出现类似此处所述的问题 Weird miscalculation when trying to detect if WebView scrolled to bottom

我发现100%有效的解决方案是根据overScroll来确定

webView.setOnOverScrolledCallback(new WebViewCustom.OnOverScrolledCallback() {
                @Override
                public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
                    if(clampedY)
                        if(scrollY == 0) {
                            //top
                        }
                        else {
                            //bottom
                        }

                }
            });

【讨论】:

  • 不错的方法。谢谢你。我认为,对于Android新手来说,看到更详细的代码片段会很有用。只需添加一些注释,例如WebView 组件应该由 setOnOverScrolledCallback 扩展,就像这里演示的一样 qaru.site/questions/15337126/…
  • 在stackoverflow中搜索了很多cmets后,这对我有用。谢谢!
  • 它仅在 API 23 及更高版本中可用。
  • 它仅适用于 API 23 及更高版本
【解决方案3】:

首先从这个类扩展你的 webview。 https://stackoverflow.com/a/14753235/3027225 像这样升级你的 webView 之后

 <com.YourPackageName.ObservableWebView
            android:id="@+id/webView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true" />

最后重写 onScroll 方法,如下所示:

webView.setOnScrollChangedCallback(new OnScrollChangedCallback() {

            @Override
            public void onScroll(int l, int t) {
                  int tek = (int) Math.floor(webView.getContentHeight() * webView.getScale());
                  if(tek - webView.getScrollY() == webView.getHeight())
                     Toast.makeText(getActivity(), "End", Toast.LENGTH_SHORT).show();


            }
        });

【讨论】:

    【解决方案4】:

    这三种方法组合对我来说效果很好

    1. 创建两个布尔变量,两个检测 topReached 或 bottomReached。

    2. 使用 computeVerticalScrollRange() 获取垂直滚动范围。 当内容高度较小时,computeVerticalScrollRange() 将为您提供帮助(在这种情况下,不调用 onScrollChanged)。

    3. 使用 onScrollChanged 检测滚动是否发生。 正在滚动表示内容高度大于 webView 测量的高度。现在使用 newt 检测底端或使用 newt 检测顶部。
    private boolean topReached = false, bottomReached = false;
    
     @Override
    protected int computeVerticalScrollRange() {
    
        int readerViewHeight = getMeasuredHeight();
    
        int verticalScrollRange = super.computeVerticalScrollRange();
    
    
        if (readerViewHeight >= verticalScrollRange) {
    
            topReached = true;
    
            bottomReached = true;
    
        }
    
        return verticalScrollRange;
    }
    
    @Override
    protected void onScrollChanged(int newLeft, int newTop, int oldLeft, int oldTop) {
    
        Logger.i(TAG, "onScrollChanged");
    
        topReached = false;
    
        bottomReached = false;
    
        Log.i(TAG, "onScrollChanged newLeft : " + newLeft);
        Log.i(TAG, "onScrollChanged newTop : " + newTop);
        Log.i(TAG, "onScrollChanged oldLeft : " + oldLeft);
        Log.i(TAG, "onScrollChanged oldTop : " + oldTop);
    
        int readerViewHeight = getMeasuredHeight();
    
        int contentHeight = getContentHeight();
    
        if (newTop == 0) {
    
            Log.d(TAG, "onScrollChanged : Top End");
    
            topReached = true;
    
        } else if (newTop + readerViewHeight >= contentHeight) {
    
            Log.d(TAG, "onScrollChanged : Bottom End");
    
            bottomReached = true;
    
        }
    
        super.onScrollChanged(newLeft, newTop, oldLeft, oldTop);
    
    }
    

    【讨论】:

      【解决方案5】:

      在 android 版本 8-11 上检查了这一点。它100%有效。我通过使用computeVerticalScrollRangecomputeVerticalScrollExtent 实现了它。以下是活动/片段中的webview 示例。

      创建一个自定义的 webview 类。

      public class MyWebView extends WebView {
          public MyWebView(Context context) {
              super(context);
          }
      
          public MyWebView(@NonNull Context context, @Nullable AttributeSet attrs) {
              super(context, attrs);
          }
      
          @Override
          public int computeVerticalScrollRange() {
              return super.computeVerticalScrollRange();
          }
      
          @Override
          protected int computeVerticalScrollExtent() {
              return super.computeVerticalScrollExtent();
          }
      }
      

      在您的布局文件中,像这样实现 webview,并在需要时将此布局文件包含到您的 activityfragment 视图文件中。

       <in.package.folder.MyWebView
              android:id="@+id/webview"
              android:layout_width="match_parent"
              android:layout_height="0dp"/>
      

      在您想要拥有网络视图的活动/片段中

      1. 声明变量
      private MyWebView webView;
      
      1. 找到元素id并初始化webView
       webView = (MyWebView) findViewById(R.id.webview);
      
      1. 使用webview 类中定义的computeVerticalScrollRangecomputeVerticalScrollExtent 方法计算滚动结束。如果滚动已到达 webview 内容的末尾,则第三个参数 i1 (Scroll Y) 将等于 (computeVerticalScrollRange - computeVerticalScrollExtent)
       webView.setOnScrollChangeListener((view, i, i1, i2, i3) -> {
                  int r1 = webView.computeVerticalScrollRange();
                  int r2 = webView.computeVerticalScrollExtent();
                  if (i1 == (r1 - r2)) {
                      "REACHED END OF THE SCROLL"
                  } 
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-05
        • 2017-10-02
        相关资源
        最近更新 更多