2012-12-27 13 views
6

Moja aplikacja na Androida korzysta z WebView, aby wyświetlać zestaw kodu HTML, który generuję "w locie". Kod HTML jest ładowany za pomocą następującego kodu:Skok WebView do zakotwiczenia za pomocą metody 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); 

To wszystko działa naprawdę ładnie. Zauważ, że nie ładuję rzeczywistego pliku HTML, tylko tworzę ciąg znaków, który reprezentuje jakiś (miejmy nadzieję, poprawny) HTML i ładuję go w WebView.

W każdym razie wygenerowany przeze mnie HTML (część w metodzie "getThreadBody") zawiera nazwane kotwice, na przykład w ten sposób;

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

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

Teraz w niektórych przypadkach Chcę WebView, aby przejść do jednego z tych kotwic jak najszybciej załadować HTML. O ile rozumiem, WebView obsługuje nawigację (przewijanie w tym przypadku) do nazwanych kotwic, ale złapanie jest takie, że nikt nie klika żadnych hiperłączy do tych kotwic, chcę, żeby WebView przewijał się po załadowaniu (nie ma problemu, jeśli jest tam jest krótkie opóźnienie między ładowaniem HTML a przewijaniem, moim celem jest to, że nie powinno to wymagać interakcji użytkownika).

Uważam, że zachowanie można osiągnąć stosując metodę loadUrl w Webview i dostarczanie URL z kotwicy w miejscu, np

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

Jednakże, ponieważ nie jestem zapisywania HTML do dowolnego pliku nie mogę używać ta metoda ... Oczywiście zapisanie kodu HTML do pliku tymczasowego może być rozwiązaniem, ale chciałbym zachować to w ostateczności, musi być prostszy sposób?

Jak mogę to osiągnąć? Dzięki!


Rozwiązane Oto kod, który działa. Znalazłem krótkie opóźnienie było konieczne aby strona załadowała się przed wykonaniem JavaScript inaczej to był rodzaj 50/50 czy to działa czy nie ...

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

Odpowiedz

6

Jak o nią sterować za pomocą JavaScript? Nie próbowałem, ale może to jest wskazówka.

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

Zapamiętaj włącz javascript dla WebView.

---- Dodatkowe Odpowiedź ----

Widziałem, że używasz TimerTask załadować JavaScript, który działa, ale myślę, że nie ma innego lepszego sposobu. WebView ma wywołanie zwrotne o nazwie naPageFinished i będzie ono wyzwalane, gdy WebView zakończy ładowanie strony. Możesz tam wstrzyknąć swój JS.

webContents.setWebViewClient(new WebViewClient(){ 

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

}); 

Mam nadzieję, że to będzie przydatne!

+0

Nie wiedziałem, że to możliwe, dzięki! –

+0

Tylko jedna uwaga, przy korzystaniu z tego URL strony internetowej nie zmienia się. webview.getUrl() zwraca ten sam URL, który został użyty do załadowania zawartości. – Codebeat

+0

Możesz również użyć javascript do obsługi wymiany danych za pomocą zdarzenia hashchange: $ j (window) .bind ('hashchange', function (e) {do twoich rzeczy tutaj} – Codebeat

2

Po pierwsze, nie trzeba używać javascript.Po załadowaniu zawartości z

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

można po prostu przejść do zakotwiczenia z

webContents.loadUrl("some_dummy_url#anchor"); 

drugie, robi to na onPageFinished bez dodatkowych wyników kontroli w niekończącą się pętlę! Kiedy loadUrl kończy na stroniePageFinished get jest wywoływany raz za razem.

+1

to nie działa dla mnie ... kiedy ja uruchom "webContents.loadUrl (" some_dummy_url # anchor ")" dostaję pustą stronę ... wszelkie pomysły? – JannGabriel

+0

Zrobiłem: .loadDataWithBaseURL ("app: html", ...) ;. Jak mówi, po prostu jakiś fałszywy URL. – 476rick

0

jeśli załadować HTML z assets:

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

i można przejść do kotwicy wewnątrz strony:

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

Jeśli masz działań zewnętrznych (np: onclick event), spróbuj tego kodu

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