2012-12-27 15 views
6

Meine Android-App verwendet eine WebView, um eine Reihe von HTML-Code anzuzeigen, die ich 'on the fly' erzeuge. Der HTML-Code geladen wird mit dem folgenden Code:WebView zum Anker springen mit loadDataWithBaseUrl

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

Das alles wirklich schön funktioniert. Beachten Sie, dass ich keine tatsächliche HTML-Datei lade. Ich erstelle lediglich eine Zeichenfolge, die einen (hoffentlich gültigen) HTML-Code darstellt, und lade ihn in der WebView.

Wie auch immer, der HTML-Code, den ich generiere (der Teil in der Methode 'getThreadBody'), enthält benannte Anker, zum Beispiel so;

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

    <a name="895984">Anchor 2</a> 
    <div>...</div> 
</div> 

Jetzt in einigen Fällen möchte ich die WebView zu einem dieser Anker zu navigieren, sobald ich den HTML-Code zu laden. Soweit ich weiß, unterstützt das WebView das Navigieren (in diesem Fall scrollen) zu benannten Ankern, aber der Haken ist, dass niemand auf Hyperlinks zu diesen Ankern klickt. Ich möchte, dass das WebView scrollt, wenn es geladen wird (dort ist es kein Problem) ist eine kurze Verzögerung zwischen dem Laden des HTML und Scrollen, mein Punkt ist, dass es keine Benutzerinteraktion erfordern sollte).

ich das Verhalten glauben kann durch die Verwendung der WebView der loadURL Verfahrens und liefert eine URL mit dem Anker an Ort und Stelle, zB

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

jedoch erreicht werden, da ich nicht die HTML auf jede Datei speichere ich kann nicht verwenden Diese Methode ... Natürlich könnte das Speichern des HTML in einer temporären Datei eine Lösung sein, aber ich möchte das als letzten Ausweg beibehalten, es muss einen einfacheren Weg geben?

Wie kann ich das erreichen? Vielen Dank!


Gelöst Hier ist der Code, der funktioniert. Ich fand eine kurze Verzögerung erforderlich war, die Seite zu laden zu lassen, bevor die JavaScript, sonst Ausführung es Art von 50/50 war, ob es oder nicht ...

arbeitete
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); 

Antwort

6

Wie wäre es Kontrolle durch JavaScript? Ich habe es nicht versucht, aber vielleicht ist das ein Hinweis.

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

Denken Sie daran, Javascript für WebView zu aktivieren.

---- Zusätzliche Antwort ----

ich sah, dass Sie verwenden, um die Timertask Javascript zu laden, das funktioniert aber ich denke, es gibt einen anderen besseren Weg. WebView hat einen Callback namens onPageFinished und wird ausgelöst, wenn WebView das Laden der Webseite beendet. Du könntest deine JS dort injizieren.

webContents.setWebViewClient(new WebViewClient(){ 

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

}); 

Hoffe, das ist nützlich!

+0

Ich wusste nicht, dass das möglich war, danke! –

+0

Nur ein Hinweis, wenn Sie dies verwenden, ändert sich die URL der Webansicht nicht. webview.getUrl() gibt dieselbe URL zurück, mit der der Inhalt geladen wurde. – Codebeat

+0

Sie können Javascript auch verwenden, um die haschange zu handhaben, indem Sie das hashchange Ereignis verwenden: $ j (Fenster) .bind ('hashchange', Funktion (e) {machen Sie Ihre Sachen hier} – Codebeat

2

Zunächst müssen Sie kein Javascript verwenden.Wenn Sie Inhalte geladen mit

webContents.loadDataWithBaseURL("some_dummy_url",...); 

können Sie einfach mit

webContents.loadUrl("some_dummy_url#anchor"); 

Zweitens zu verankern bewegen, dass ohne zusätzliche Kontrollergebnisse auf onPageFinished tun in nie Schleife endet! Wenn loadUrl onPageFinished beendet wird, wird get immer wieder aufgerufen.

+1

das funktioniert nicht für mich ... wenn ich führe die "webContents.loadUrl (" some_dummy_url # anchor ");" Ich bekomme eine leere Seite ... irgendwelche Ideen? – JannGabriel

+0

Ich tat: .loadDataWithBaseURL ("app: html", ...) ;. Wie er sagt, nur eine Dummy-URL – 476rick

0

, wenn Sie den HTML-Code aus dem assets laden:

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

und Sie können innerhalb einer Web-Seite an den Anker bewegen:

webView.loadUrl("http://www.stackoverflow.com/mypage.html#anchor"); 
0

Falls Sie externe Aktion (zB: onclick event), versuchen Sie diesen Code

public static void scrollToAnchor(String id) { 
     sWebView.loadUrl("javascript:document.getElementById(\"" + id + "\").scrollIntoView()"); 
} 
Verwandte Themen