WebView使用loadDataWithBaseUrl跳转到锚点

Nic*_*sen 7 anchor android scroll webview

我的Android应用程序使用WebView显示我在"即时"生成的一堆HTML代码.使用以下代码加载HTML代码:

    StringBuilder builder = new StringBuilder();

    // HTML
    builder.append("<html><head><link rel=\"stylesheet\" href=\"file:///android_asset/style.css\" type=\"text/css\">");
    builder.append("</link></head><body>");
    builder.append(getThreadBody());
    builder.append("</body></html>");

    webview.loadDataWithBaseURL("file:///android_asset/", builder.toString(), "text/html", "utf-8", null);
Run Code Online (Sandbox Code Playgroud)

一切都很好.请注意,我没有加载实际的HTML文件,我只是创建一个代表一些(希望是有效的)HTML的字符串并将其加载到WebView中.

无论如何,我生成的HTML('getThreadBody'方法中的部分)包含命名锚点,例如像这样;

<div>
    <a name="949823">Anchor 1</a>
    <div>All kinds of stuff</div>

    <a name="895984">Anchor 2</a>
    <div>...</div>
</div>
Run Code Online (Sandbox Code Playgroud)

现在在某些情况下,我希望WebView在加载HTML后立即导航到其中一个锚点.据我所知,WebView支持导航(在这种情况下滚动)到命名锚点,但问题是没有人点击任何超链接到这些锚点,我希望WebView在加载时滚动(如果那里没有问题)加载HTML和滚动之间的短暂延迟,我的观点是它不应该要求用户交互).

我相信这种行为可以通过使用WebView的loadUrl方法并提供一个带有锚点的URL来实现,例如

webview.loadUrl("file:///android_asset/page.html#895984", ...)
Run Code Online (Sandbox Code Playgroud)

但是,由于我没有将HTML保存到任何文件,我无法使用此方法...当然,将HTML保存到临时文件可能是一个解决方案,但我想保留它作为最后的手段,必须有一个更简单的方法?

我怎样才能做到这一点?谢谢!


已解决 这里是有效的代码.我发现在执行javascript之前让页面加载需要很短的延迟,否则它是50/50是否有效...

    StringBuilder builder = new StringBuilder();

    // HTML
    builder.append("<html><head><link rel=\"stylesheet\" href=\"file:///android_asset/style.css\" type=\"text/css\">");
    builder.append("</link>");
    builder.append("<script>");
    builder.append("function scrollAnchor(id) {");
    builder.append("window.location.hash = id;}");
    builder.append("</script>");
    builder.append("</head><body>");
    builder.append(getThreadBody());
    builder.append("</body></html>");

    webContents.loadDataWithBaseURL("file:///android_asset/", builder.toString(), "text/html", "utf-8", null);

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            String id = "895884";
            webContents.loadUrl("javascript:scrollAnchor(" + id + ");");
        }
        }
    }, 250);
Run Code Online (Sandbox Code Playgroud)

way*_*bai 6

如何通过JavaScript控制它?我没试过,但也许这是一个线索.

builder.append(getThreadBody());
builder.append("<script>window.location.hash="949823";</script>");
builder.append("</body></html>");
Run Code Online (Sandbox Code Playgroud)

请记住为WebView启用javascript.

----补充答案----

我看到你使用TimerTask加载javascript,这有效,但我认为还有另一种更好的方法.WebView有一个名为onPageFinished的回调,它将在WebView完成加载网页时触发.你可以在那里注入你的JS.

webContents.setWebViewClient(new WebViewClient(){

    @Override
    public void onPageFinished(WebView view, String url) {
          String id = "895884";
          webContents.loadUrl("javascript:scrollAnchor(" + id + ");");
    }

});
Run Code Online (Sandbox Code Playgroud)

希望这很有用!


小智 6

首先,您不需要使用 javascript。如果您加载了内容

webContents.loadDataWithBaseURL("some://dummy/url",...);
Run Code Online (Sandbox Code Playgroud)

你可以简单地滚动到锚点

webContents.loadUrl("some://dummy/url#anchor");
Run Code Online (Sandbox Code Playgroud)

其次,在没有额外控制的情况下在 onPageFinished 上执行此操作会导致永无止境的循环!当 loadUrl 完成 onPageFinished 时,会一次又一次地调用。