我的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);
答案 0 :(得分: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 + ");");
}
});
希望这很有用!
答案 1 :(得分:4)
首先,您不需要使用javascript。如果您使用
加载内容webContents.loadDataWithBaseURL("some://dummy/url",...);
您只需使用
滚动到锚点即可webContents.loadUrl("some://dummy/url#anchor");
其次,在没有额外控制的onPageFinished上执行此操作会导致永无止境的循环!当loadUrl完成onPageFinished时,会一次又一次地调用。
答案 2 :(得分:1)
如果您有外部操作(例如:onclick event
),请尝试使用此代码
public static void scrollToAnchor(String id) {
sWebView.loadUrl("javascript:document.getElementById(\"" + id + "\").scrollIntoView()");
}
答案 3 :(得分:0)
如果你从assets
加载html:
webView.loadUrl("file:///android_asset/htmls/mypage.html#anchor");
您可以移动到网页内的锚点:
webView.loadUrl("http://www.stackoverflow.com/mypage.html#anchor");
答案 4 :(得分:0)
如果您的布局中的webview位于nestedScrollView内,则该嵌套将阻止滚动事件正常工作。取出后,无需重新加载或添加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>