如何以编程方式滚动 Android WebView

Posted

技术标签:

【中文标题】如何以编程方式滚动 Android WebView【英文标题】:How to Programmatically Scroll Android WebView 【发布时间】:2011-01-15 09:16:32 【问题描述】:

我正在尝试以编程方式将 WebView 滚动到 DOM 树中特定元素的位置。但到目前为止,我还无法让 WebView 响应滚动请求。我尝试调用使用 window.scrollTo(...)javascript,但 WebView 没有响应。在 Java 方面,我尝试调用 WebView.flingScroll(...) 方法。 WebView 将响应flingScroll,但我需要的是scrollTo(...) 功能。有什么想法吗?

【问题讨论】:

【参考方案1】:

我找到了一个更好的答案来解决这个问题。事实证明,WebView 确实具有您所期望的 scrollTo()getScrollX()getScrollY() 方法。它们在文档中有点隐藏,因为它们继承自 View(通过 AbsoluteLayout -> ViewGroup -> View)。这显然是比有些繁琐的 JavaScript 界面更好的方式来操纵WebView 的滚动位置。

【讨论】:

很高兴你回来添加这个:) 这是一个很好的解决方案。但我想做一些额外的事情。我有一个包含学校课程(带有一些标签)的 html 文件,以及一个包含该课程解释录音的音频文件。我想根据在后台播放的音频文件滚动我的 web 视图(包含 html 文件)。如果我转发音频文件,那么我的滚动条也会移动到当前播放音频的位置。你有什么建议吗? @Steve:它对我来说很好用,但我想在顶部滚动网页视图(即网页视图的开始位置)。我正在使用 mScrollView.scrollTo(0.mScrollView.getScrollY()) 但它不起作用。 @SteveLiddle:它适用于滚动视图,但不适用于 webView。我想将它应用于 webView。还有一个人认为我需要你的建议,我想在某个时间间隔内将网页视图自动滚动到特定位置。我为此使用 findAll("tag") 和 findNext(true) 。它工作正常,但它滚动到屏幕底部的“标签”,我想滚动它直到屏幕顶部的“标签”。谢谢。 @Maarten,一个元素可以报告它的位置,你可以通过编写一些 JavaScript 来获得它。我认为你想对 DOM 树做的任何事情都需要在 JavaScript 中进行,而不是在 Objective-C 中。【参考方案2】:

事实证明window.scrollTo() 确实有效,您只是不能添加自己的名为scrollTo() 的方法。出于某种原因,当我调用window.scrollTo() 时,我自己的scrollTo() 方法被调用了。

因此,总而言之,要将 WebView 滚动到特定的 DOM 元素,请编写 JavaScript 函数来进行滚动:

function scrollToElement(id) 
    var elem = document.getElementById(id);
    var x = 0;
    var y = 0;

    while (elem != null) 
        x += elem.offsetLeft;
        y += elem.offsetTop;
        elem = elem.offsetParent;
    
    window.scrollTo(x, y);

然后从您的 android 应用程序(Java 代码)中,告诉您的 WebView 加载 URL:

webView.loadUrl("javascript:scrollToElement('" + elemId + "')");

这种方法存在一些问题,例如滚动的动画效果不佳,但一般机制有效。

DOM 窗口对象确实正确报告了 WebView 的当前滚动位置(参见window.pageXOffsetwindow.pageYOffsetwindow.scrollXwindow.scrollY)。如果您只想知道 WebView 当前的滚动位置,请编写一些 JavaScript 来调用您的 Java 代码并传递 X/Y 偏移量。

【讨论】:

发生这种情况是因为在全局范围内声明函数时,它实际上被声明为全局 window 对象的属性。【参考方案3】:

使用 Java 代码无法做到这一点

对于所有被这个问题困扰的人,我有一些关于在 android 中滚动 webview 的结论。

您无法使用 Java 代码滚动 web 视图或获取滚动位置。 只能获取webview的layoutHeight、measuredHeight、contentHeight,仅此而已。这些都是允许您获取和设置滚动状态的 android api。 但是,您可以重写 onScorllChanged 为滚动 webview 事件(或 fling 事件)添加自定义侦听器,您将被通知原始位置和新位置。 好吧,您可以使用 JavaScript 代码滚动到某个位置,如下所示,但性能确实很差。如果您想经常滚动它,请三思而后行。

window.scrollTo(100,500)

考虑您的情况并选择合适的解决方案。另请注意,fling 和 scroll 是不同的东西。

【讨论】:

【参考方案4】:
    @Override
        public void onPageFinished(final WebView view, String url) 

            super.onPageFinished(view, url);

                new Handler().postDelayed(new Runnable() 

                        @Override
                        public void run() 
                                if (app.scrollCache.containsKey(app.srctid))
            
                            app.scrollSpot=app.scrollCache.get(app.srctid); 
                            view.scrollTo(0,(int)app.scrollSpot);
                            
                        pageFinished=true;
                        
                    , 200);


    

【讨论】:

【参考方案5】:

以下单行解决方案可确保将所选元素带入视野(如果不是)。在某些情况下,这可能就足够了。

webView.loadUrl("javascript:document.getElementById('"+aID+"').scrollIntoView()");

【讨论】:

以上是关于如何以编程方式滚动 Android WebView的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式在iOS上滚动UIWebView

使用 swift 以编程方式滚动到 webview 的底部

Appcelerator Webview滚动到底部?

Android 可滚动的 AlertDialog 以编程方式

Android - Javascript:如何在 webview 中执行 jquery

以编程方式滚动到 Android ListView 中的特定位置