尝试检测 WebView 是否滚动到底部时出现奇怪的计算错误

4

我有一个问题,就是无法检测到WebView滚动到底部的时刻。我使用以下代码:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);

    int bottom = ((int) Math.floor(getContentHeight() * getScale()) - getHeight());
    MyLogger.log(y + "____" + bottom);

    if (y == bottom) {
        // Trigger listener
    }
}

记录日志会输出以下内容:
162____164

某种方式,这里存在2像素的计算错误,我不知道它是从哪里出现的。

谢谢。

2个回答

12

您输入的计算是正确的。更好的表达方式为:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);
    final int DIRECTION_UP = 1;
    if (!canScrollVertically(DIRECTION_UP)) {
        // Trigger listener.
    }
}

有几种情况可能导致您无法通过此方式检测到页面底部:

  • 如果页面使用触摸处理程序处理滚动,并且pageScale()大于1.0,则会在CSS坐标空间中检测到“底部”,由于四舍五入的原因,它可能无法正确映射到android.view.View坐标空间中(尽管这应该在KitKat中得以修复)。
  • 您或您正在使用的某个库正在覆盖WebView.scrollTo/overScrollBy/等方法,不允许滚动到底部。

作为最后的解决方法,您可以重写onOverScrolled方法:

@Override
protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    if (scrollY > 0 && clampedY && !startedOverScrollingY) {
        startedOverScrollingY = true;
        // Trigger listener.
    }
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
}

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);
    if (y < oldY) startedOverScrollingY = false;
}
如果这个问题在最新的Android版本上重现,请您提交一个bug报告。最好创建一个最小化的应用程序,用一个空白(或者非常简单)的页面来重现这个问题。

好的答案,尽管我不得不在onScrollChanged中稍微更改一下公式。 - Niko
@Niko - 谢谢你指出这个问题!我已经更新了答案,使用了 canScrollVertically 方法,我认为这更好,因为它是公共方法。 - marcin.kosiba
如果您正在开发API级别14或更高版本的应用程序,那么这非常棒 :-) - Niko
Niko - 支持库提供了这个方法(http://developer.android.com/reference/android/support/v4/view/ViewCompat.html),最坏的情况下,你可以从 View.java 中复制 canScrollVertically 实现(https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java)。 - marcin.kosiba
1
完美答案。有很多其他解决方案,包括比例和地板计算,但是第一个使用canScrollVertically方法的解决方案是我唯一有效的解决方案。 - diesersamat

0

使用以下代码可以得到精确的结果:

@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
    super.onScrollChanged(x, y, oldX, oldY);

    if (y == computeVerticalScrollRange() - getHeight()) {
        // Trigger listener
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接