Android WebView报告错误的内容高度

3
我正在开发一款与 Android 相关的应用程序,该应用程序旨在加载网页,并且如果内容高度大于视图高度,则滚动内容。
问题是,在几个页面上,即使我可以手动向下滚动,WebView.getContentHeight() 似乎返回视图的确切高度。这意味着我没有正确的值来进行动画处理,滚动不会正确地工作。
目前,为了测试此问题,我已设置一个滚动更改侦听器,以在 WebView 滚动到末尾时记录消息。
        webView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
        @Override
        public void onScrollChange(View view, int i, int i1, int i2, int i3) {
            Log.d(TAG, String.format("scrollX: %d, scrollY: %d, oldScrollX: %d, oldScrollY: %d", i, i1, i2, i3));
            int height = (int) Math.floor(webView.getContentHeight() * webView.getScaleY());
            if (webView.getScrollY() + webView.getHeight() >= height && progress > 99)
                Log.d(TAG, "Reached bottom: " + height);
        }
    });

日志显示缩放内容高度为1586,Web视图高度为1586。然而,我可以手动滚动页面向下,并获得以下日志输出:

WebPageView: scrollX: 0, scrollY: 1960, oldScrollX: 0, oldScrollY: 1774
WebPageView: Reached bottom: 1773
WebPageView: scrollX: 0, scrollY: 1959, oldScrollX: 0, oldScrollY: 1960
WebPageView: Reached bottom: 1773

根据我的观察,这明显表明内容高度被错误地报告了,因为:

WebView.getScrollY() + WebView.getHeight() > WebView.getContentHeight() * WebView.getScaleY()

我已经设置了一个 WebChromeClient,并重载了 onProgressChanged() 方法。我知道当内容高度被检索到时,页面加载完成了。但是为什么 WebView 会将内容高度错误地报告为一页,实际上它比较长呢?
编辑:我在 Android 6.0、7.0 和 7.1 上运行过该应用程序。build.gradle 中的 minSdkVersion 是23,targetSdkVersion 是25。WebView 版本是44.0.2403.119。

请指明您观察到此问题的Android操作系统版本。 - j2ko
你最终解决了这个问题吗?我也遇到了同样的问题。 - Greg Ennis
1个回答

0

更新:如评论中所指出,computeVerticalScrollRange()是一个受保护的方法,因此您需要子类化WebView才能使此方法起作用。这可以通过将监听器放在子类中或创建一个访问器方法来返回受保护方法的值来实现。


不要使用getContentHeight(),而是尝试使用computeVerticalScrollRange()

滚动值以任意单位表示,但它们在返回或使用滚动值的所有不同方法中保持一致。因此,虽然内容高度可能以像素为单位,但滚动单位却不是。您需要更新代码以准确检测到滚动到底部。

在Java中:

webView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
    @Override
    public void onScrollChange(View view, int i, int i1, int i2, int i3) {
        int maxScrollRange = computeVerticalScrollRange();
        if (webView.getScrollY() + webView.getMeasuredHeight() >= maxScrollRange) {
            Log.d(TAG, "Reached the bottom.");
        }
    }
});

或者在 Kotlin 中:

webView.setOnScrollChangeListener { _,_,_,_,_ ->
    val maxScrollRange = computeVerticalScrollRange()
    if(webView.scrollY + webView.measuredHeight >= maxScrollRange) {
        Log.d(TAG, "Reached the bottom.")
    }
}

此方法受保护,无法访问。 - saltandpepper
@saltandpepper 那实际上是个很好的观点。我刚刚意识到我正在使用它在一个 WebView 子类中。我将相应地更新我的答案。 - Michael Celey

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