8

我的 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);

这一切都很好。请注意,我没有加载实际的 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>

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

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

webview.loadUrl("file:///android_asset/page.html#895984", ...)

但是,由于我没有将 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);
4

5 回答 5

6

用 JavaScript 控制它怎么样?我没有尝试过,但也许这是一个线索。

builder.append(getThreadBody());
builder.append("<script>window.location.hash="949823";</script>");
builder.append("</body></html>");

请记住为 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 + ");");
    }

});

希望这是有用的!

于 2012-12-28T02:54:12.893 回答
6

首先,您不需要使用 javascript。如果您使用

webContents.loadDataWithBaseURL("some://dummy/url",...);

你可以简单地滚动到锚点

webContents.loadUrl("some://dummy/url#anchor");

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

于 2013-12-04T10:42:27.280 回答
1

如果您的布局中有嵌套滚动视图内的 web 视图,则嵌套将阻止滚动事件正常工作。一旦你把它拿出来,它就可以工作而无需重新加载或添加 javascript。

此外,如果您想保留 nestedScrollView 并且不关心用户是否无法滚动该部分,您可以添加fillViewPort=true到 nestedScrollView 和android:layout_height="wrap_content"webview。

它看起来像:

<androidx.coordinatorlayout.widget.CoordinatorLayout>

  <com.google.android.material.appbar.AppBarLayout>
  ...
  </com.google.android.material.appbar.AppBarLayout>

  <androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:fillViewPort=true
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

     <WebView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/> 

  </androidx.core.widget.NestedScrollView>


</androidx.coordinatorlayout.widget.CoordinatorLayout>
于 2020-04-06T16:14:11.693 回答
1

如果您有外部操作(例如:)onclick event,请尝试此代码

 public static void scrollToAnchor(String id) {
        sWebView.loadUrl("javascript:document.getElementById(\"" + id + "\").scrollIntoView()");
 }
于 2017-12-17T10:24:16.813 回答
0

如果您从以下位置加载 html assets

 webView.loadUrl("file:///android_asset/htmls/mypage.html#anchor");

您可以移动到网页内的锚点:

webView.loadUrl("http://www.stackoverflow.com/mypage.html#anchor");
于 2015-09-17T20:35:04.153 回答