2012-12-27 4 views
6

La mia app Android utilizza una WebView per visualizzare un mucchio di codice HTML che io genera "al volo". Il codice HTML viene caricato utilizzando il seguente codice:WebView salta per ancorare utilizzando 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); 

Tutto questo funziona davvero bene. Nota che non sto caricando un vero file HTML, sto semplicemente creando una stringa che rappresenta un codice HTML (si spera valido) e lo carica nella WebView.

In ogni caso, l'HTML I generato (la parte nel metodo 'getThreadBody') contiene ancore con nome, ad esempio in questo modo;

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

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

Ora, in alcuni casi, voglio il WebView per navigare ad una di quelle ancore non appena si carica il codice HTML. Per quanto ne so, WebView supporta la navigazione (scorrendo in questo caso) alle ancore con nome, ma il problema è che nessuno fa clic su nessun collegamento ipertestuale a tali ancore, voglio che la WebView scorra quando viene caricata (non c'è problema se è un breve ritardo tra il caricamento dell'HTML e lo scorrimento, il mio punto è che non dovrebbe richiedere l'interazione dell'utente).

Credo che il comportamento può essere ottenuto utilizzando il metodo loadURL del WebView e fornendo un URL con l'ancora in atto, per esempio

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

Tuttavia, dato che non sto salvando il codice HTML a qualsiasi file non posso usare questo metodo ... Naturalmente salvare l'HTML in un file temporaneo può essere una soluzione, ma mi piacerebbe tenerlo come ultima risorsa, ci deve essere un modo più semplice?

Come posso ottenere questo risultato? Grazie!


Risolto Ecco il codice che funziona. Ho trovato un piccolo ritardo è stato richiesto di lasciare che il caricamento della pagina prima di eseguire il javascript altrimenti era una sorta di 50/50 se ha funzionato o no ...

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

risposta

6

ne dite di controllo è da JavaScript? Non l'ho provato ma forse questo è un indizio.

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

Ricordare abilitare javascript per WebView.

---- ---- aggiuntive risposta

ho visto che si utilizza TimerTask per caricare il javascript, che funziona ma penso che c'è un altro modo migliore. WebView ha un callback denominato onPageFinished e verrà attivato quando WebView terminerà il caricamento della pagina Web. Potresti inserire il tuo JS lì.

webContents.setWebViewClient(new WebViewClient(){ 

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

}); 

Spero che questo sia utile!

+0

Non sapevo che fosse possibile, grazie! –

+0

Solo una nota, quando si utilizza questo l'URL della visualizzazione Web non cambia. webview.getUrl() restituisce lo stesso URL utilizzato per caricare il contenuto. – Codebeat

+0

Puoi anche usare javascript per gestire l'haschange usando l'evento hashchange: $ j (window) .bind ('hashchange', function (e) {fai la tua roba qui} – Codebeat

2

Prima di tutto, non è necessario utilizzare javascript.Se avete caricato i contenuti con

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

si può semplicemente scorrere per ancorare con

webContents.loadUrl("some_dummy_url#anchor"); 

In secondo luogo, facendo che in onPageFinished senza risultati di controllo supplementari nel ciclo senza fine! Quando loadUrl termina suPageFinished viene chiamato ancora e ancora.

+1

questo non funziona per me ... quando io eseguire "webContents.loadUrl (" some_dummy_url # anchor ");" ottengo una pagina vuota ... qualche idea? – JannGabriel

+0

Ho fatto: .loadDataWithBaseURL ("app: html", ...) ;. Come dice lui, solo qualche URL fittizio. – 476rick

0

se si carica il codice HTML del assets:

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

e si può passare per l'ancora all'interno di una pagina web:

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

Se si dispone di azione esterna (ad esempio: onclick event), prova questo codice

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