it-swarm.com.de

Zeigen Sie gut aussehende mathematische Formeln in Android an

Es ist traurig zu sehen, dass Wissenschaft und Mathematik auf der Android-Plattform nie genug Beachtung finden. Vielleicht ist das ein einfaches Problem, aber ich bin insgesamt dude in Javascript, daher habe ich Mühe zu verstehen, wie ich dieses Problem lösen kann.

Was ich tun möchte, ist einfach: Ich muss nur mathematische Gleichungen rendern. Es kann MathJax oder JqMath sein oder alles, was klein und schnell ist. Wie kann ich in einer Webansicht einfachen Text in Absätzen und formatierten Gleichungen anzeigen?

(jeder kommt mit anderen Methoden heraus, die offensichtlich funktionieren, ich werde das auch als Lösung betrachten)

WAS ICH GEMACHT HABE SO FAR:

Ich habe mit MathJax begonnen, um Formeln in die Webansicht zu integrieren (Ich weiß nicht, ob es einen erfolgreichen jqMath-Anwendungsfall gibt? Jeder möchte seine Erfahrungen teilen?) Ich kann alle Funktionen genau so reproduzieren wie die des Standalone MathJax App . In dieser App gibt ein Benutzer eine Zeichenfolge in das EditText-Feld ein und MathJax rendert die Formel in Latex, sobald der Benutzer eine Schaltfläche zur Bestätigung drückt.

Ich brauche keinen Benutzer zur Bestätigung. Ich dachte, das sollte einfacher sein, da es keine Benutzerinteraktion gibt, aber irgendwie wird die Gleichung nie angezeigt. Ich weiß, dass mir etwas fehlen muss, da die Codes im eigenständigen MathJax für Benutzereingaben bestimmt sind. Welchen Teil des Codes muss ich ändern, um eine Gleichung direkt aus einer Zeichenfolge zu rendern, z. B.\sqrt {b ^ 2-4ac}? Hier ist der anfängliche Header für die Webansicht:

WebView w = (WebView) findViewById(R.id.webview);
w.getSettings().setJavaScriptEnabled(true);
w.getSettings().setBuiltInZoomControls(true);
w.loadDataWithBaseURL("http://bar", "<script type='text/x-mathjax-config'>"
                        +"MathJax.Hub.Config({ showMathMenu: false, "
                        +"jax: ['input/TeX','output/HTML-CSS'], "
                        +"extensions: ['tex2jax.js'], " 
                        +"TeX: { extensions: ['AMSmath.js','AMSsymbols.js',"
                        +"'noErrors.js','noUndefined.js'] } "
                        +"});</script>"
                        +"<script type='text/javascript' "
                        +"src='file:///Android_asset/MathJax/MathJax.js'"
                        +"></script><span id='math'></span>","text/html","utf-8","");

Und so wird die ursprüngliche Webansicht geladen, wenn der Benutzer nach der Eingabe in edittext eine Schaltfläche drückt:

WebView w = (WebView) findViewById(R.id.webview);
EditText e = (EditText) findViewById(R.id.edit);
w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
                  +doubleEscapeTeX(e.getText().toString())
                  +"\\\\]';");
w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");

private static String doubleEscapeTeX(String s) {
    String t="";
    for (int i=0; i < s.length(); i++) {
        if (s.charAt(i) == '\'') t += '\\';
        if (s.charAt(i) != '\n') t += s.charAt(i);
        if (s.charAt(i) == '\\') t += "\\";
    }
    return t;
}

Ich habe versucht, durch eine fest codierte Zeichenfolge zu ersetzen

w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
                  +doubleEscapeTeX("sample string")
                  +"\\\\]';");

aber es funktioniert nicht, der Text "sample string" wird nicht einmal in der Webansicht angezeigt.

[LÖSUNG] siehe Joes Antwort

Um seine Antwort zu erläutern, ist dies ein Beispiel dafür, wie Sie einen Satz im Klartext setzen und dann eine formatierte Gleichung in Anzeigeform anzeigen (alles in einer einzigen Webansicht):

Ersetzen Sie die letzte Zeile um

+"></script><span id='math'></span>","text/html","utf-8","");

mit

+"></script><span id='text'>This is plain text.</span> <span id='math'></span>", "text/html", "utf-8", "");

Dann ruf an

w.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
        if (!url.startsWith("http://bar"))
            return;
        w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
                    +doubleEscapeTeX("\\sqrt{b^2-4ac}") + "\\\\]';");
        w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
    }
});

Dadurch wird eine Zeichenfolge Dies ist normaler Text in der normalen Schriftart festgelegt und die Formel in der Mitte angezeigt foo+bar in der Webansicht.

EDIT (Android 4.4 Ausgabe)

Ab Android KitKat müssen Sie alle Zeilen loadUrl(...) durch evaluateJavascript(...) ersetzen. Da dies jedoch nur für KitKat (API 19 oder höher) verfügbar ist, müssen Sie zuerst eine SDK-Versionsprüfung durchführen. Zum Beispiel:

if (Android.os.Build.VERSION.SDK_INT < 19) {
    w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
} else {
    w.evaluateJavascript("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);",null);
}

UPDATE (AB MATHJAX 2.5)

Da sich Ordner ändern, funktioniert der vorherige Code in der neuesten Version von MathJax nicht. Außerdem verwendet die empfohlene Methode zum Minimieren der Größe von lokalem MathJax jetzt Grunt . Die Vorlage zum Verkleinern von MathJax finden Sie hier .

Angenommen, Sie haben MathJax erfolgreich verkleinert und die Ausgabe von HTML-CSS vorausgesetzt, dann ist hier eine einfache Version, die MathJax laden kann:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    final WebView w = (WebView) findViewById(R.id.webview);
    w.getSettings().setJavaScriptEnabled(true);
    w.getSettings().setBuiltInZoomControls(true);

    String Url = "</style>"
                 + "<script type='text/x-mathjax-config'>"
                 + "  MathJax.Hub.Config({" + "    showMathMenu: false,"
                 + "             jax: ['input/TeX','output/HTML-CSS', 'output/CommonHTML'],"
                 + "      extensions: ['tex2jax.js','MathMenu.js','MathZoom.js', 'CHTML-preview.js'],"
                 + "         tex2jax: { inlineMath: [ ['$','$'] ], processEscapes: true },"
                 + "             TeX: {" + "               extensions:['AMSmath.js','AMSsymbols.js',"
                 + "                           'noUndefined.js']" + "             }"
                 + "  });"
                 + "</script>"
                 + "<script type='text/javascript' src='file:///Android_asset/MathJax/MathJax.js'>"
                 + "</script>"
                 + "<p style=\"line-height:1.5; padding: 16 16\" align=\"justify\">"
                 + "<span >";

    // Demo display equation
    url += "This is a display equation: $$P=\frac{F}{A}$$";

    url += "This is also an identical display equation with different format:\\[P=\\frac{F}{A}\\]";

    // equations aligned at equal sign
    url += "You can also put aligned equations just like Latex:";
    String align = "\\begin{aligned}"
                + "F\\; &= P \\times A \\\\ "
                + "&= 4000 \\times 0.2\\\\"
                + "&= 800\\; \\text{N}\\end{aligned}"; 
    url += align;

    url += "This is an inline equation \\sqrt{b^2-4ac}.";

    // Finally, must enclose the brackets
    url += "</span></p>";

    mWebView.loadDataWithBaseURL("http://bar", url, "text/html", "utf-8", "");
    mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (!url.startsWith("http://bar")) return;
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KitKat) {
                view.loadUrl(JAVASCRIPT);
            } else {
                view.evaluateJavascript(JAVASCRIPT, null);
            }
        }
    });
}

Anders als bei Joes 'Antwort müssen weder Text noch mathematische Typen getrennt werden. MathJax formatiert sie lediglich entsprechend.

Es scheint jedoch einen Fehler zu geben, bei dem Webview in KitKat-Geräten keinen Großbuchstaben "A" darstellen kann. Jeder, der einen Weg kennt, ist willkommen, einen Workaround dafür bereitzustellen.

27
Neoh

Wenn ich Ihr Problem richtig verstehe, scheint das Problem darauf zurückzuführen zu sein, dass die MathJax-Bibliothek nicht vollständig geladen wurde (vom Aufruf loadDataWithBaseURL()), wenn Sie die zusätzlichen loadUrl()s aufrufen, um die Formel anzuzeigen. Die einfachste Lösung besteht darin, auf den Rückruf von onPageFinished() zu warten, um den Anruf zu tätigen.

Zum Beispiel scheint der folgende Code auf meinem gut zu funktionieren:

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    final WebView w = (WebView) findViewById(R.id.webview);
    w.getSettings().setJavaScriptEnabled(true);
    w.getSettings().setBuiltInZoomControls(true);
    w.loadDataWithBaseURL("http://bar", "<script type='text/x-mathjax-config'>" 
            + "MathJax.Hub.Config({ "
            + "showMathMenu: false, " 
            + "jax: ['input/TeX','output/HTML-CSS'], " 
            + "extensions: ['tex2jax.js'], "
            + "TeX: { extensions: ['AMSmath.js','AMSsymbols.js'," 
            + "'noErrors.js','noUndefined.js'] } "
            + "});</script>" 
            + "<script type='text/javascript' " 
            + "src='file:///Android_asset/MathJax/MathJax.js'"
            + "></script><span id='math'></span>", "text/html", "utf-8", "");
    w.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (!url.startsWith("http://bar")) return;
            w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
                    + doubleEscapeTeX("sample string") + "\\\\]';");
            w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
        }
    });
}

Update : Um zusätzliche Ausgaben in WebView zu ermöglichen, würde ich vorschlagen, HTML-Elemente zum ersten Aufruf von loadDataWithBaseURL() hinzuzufügen. Also für das obige Beispiel anstelle dieser Zeile am Ende:

            + "></script><span id='math'></span>", "text/html", "utf-8", "");

Wir können Folgendes tun:

            + "></script><span id='text'>Formula:</span>"
            + "<span id='math'></span>", "text/html", "utf-8", "");

Wenn Sie diesen Teil anschließend interaktiv aktualisieren müssen, können Sie den gleichen Mechanismus verwenden, den wir für den Teil "Mathe" verwendet haben.

            w.loadUrl("javascript:document.getElementById('text').innerHTML='"
                    + newText + "';");

Sie können auch andere HTML-Elemente (anstelle des oben genannten <span>) verwenden, wenn Sie eine bestimmte Formatierung wünschen.

21
Joe

Anstatt Javascript und Javascript-Bibliotheken zu verwenden, um die LaTeX-Clientseite zu rendern, sollten Sie Folgendes tun:

  1. Schreiben Sie eine serverseitige Funktion, die eine LaTeX-Zeichenfolge verwendet und eine Image-Datei erstellt. Sie können dies mit dem Standard-LaTeX-Befehlszeilentool "out of the box" tun. (Dies scheint etwas zu sein, wozu Sie in der Lage sind, und das Problem besteht darin, dass das Rendern clientseitig erfolgt.)

  2. Erstellen Sie auf Ihrer Website/Ihrem Dienst einen Endpunkt, der wie folgt aussieht:
    GET /latex?f={image format}&s={latex string}

  3. Verwenden Sie auf Ihren Webseiten ein einfaches HTML <img/> -Tag, um Ihr LaTeX zu rendern. Zum Beispiel:
    <img src="/latex?f=jpeg&s=f%40x%41%61x%942"/>
    gibt die f(x)=x^2-Gleichung als JPEG aus.

  4. (Optional) Erstellen Sie einen einfachen serverseitigen Cache für (f,s)-Paare, sodass Sie eine bestimmte LaTeX-Zeichenfolge nur bei der ersten Anforderung rendern, die für diese bestimmte Zeichenfolge (von einem beliebigen Client) erfolgt. Als erster Prototyp könnten Sie nur ein Serververzeichnis haben, in dem Sie Dateien mit dem Namen {hash(s)}.{f} haben, wobei hash nur eine Hash-Funktion wie SHA1 ist.

Dies entlastet Sie von dem Versuch, alles clientseitig mit Javascript arbeiten zu lassen. Und ich würde argumentieren (obwohl einige anderer Meinung sein mögen), dass dies viel sauberer ist. Alles, was Sie an den Kunden senden, ist:

  1. das HTML-Tag <img/>
  2. der tatsächliche Bildinhalt, wenn der Browser das Attribut src auflöst

Sehr leicht und schnell!

5
Timothy Shields

Das "Capital A" -Problem ist ein bekannter Fehler von MathJax auf Android WebView. Sie können die Schriftdateien durch optimierte Schriftdateien ersetzen. Das Update funktioniert, wenn die HTML-CSS-Ausgabe mit TeX-Schriftarten verwendet wird. Neben MathJax können Sie auch KaTeX ausprobieren, das zwar weniger schön, aber schneller ist.

Eigentlich habe ich beide in eine benutzerdefinierte Android-Ansicht gepackt, siehe MathView .

2
kexanie

Spät zur Party, aber ich denke, ich habe eine bessere Lösung als Joes. Die ursprüngliche Frage gestellt:

wie kann ich einfachen Text in einem Absatz und eine formatierte Gleichung in derselben Webansicht anzeigen?

Im ursprünglichen Beispiel hatten wir:

w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
                  +doubleEscapeTeX("sample string")
                  +"\\\\]';");

Merkst du den \\\\[ und den \\\\]? Diese vier umgekehrten Schrägstriche werden von LaTeX nur als einer interpretiert, und \[ und \] in LaTeX ist eine Abkürzung für\begin{equation}... \end{equation}, die einen Block angezeigter Mathematik erzeugt. Wenn wir einen Textabschnitt mit einigen Gleichungen innerhalb des Abschnitts wollen, müssen wir den \\\\[ loswerden und den LaTeX-Befehl \( und \) verwenden. Der Code für ein Beispiel mit Absatzmathematik und angezeigter Mathematik wäre:

w.loadUrl("javascript:document.getElementById('math').innerHTML='"
   +doubleEscapeTeX(
           "This is a second degree equation \\( \\small ax^2+bx+c=0\\) and its "
          +"roots are \\[x=\\frac{-b\\pm \\sqrt{b^2-4ac}}{2a}. \\]"
    )+"';");

Das WebView wird: enter image description here Anmerkungen:

  • Wir brauchen nur zwei Backslashes anstelle von vier, weil wir uns in doubleEscapeTeX() befinden und diese Funktion die Backslashes dupliziert.

  • Auch der Text außerhalb der mathematischen Umgebungen wird mit HTML gerendert (innerhalb des Tags <span id='math'>).

  • Die LaTeX-Schriftart ist größer als die HTML-Schriftart. Wenn Sie also in jeder mathematischen Umgebung einen \\small hinzufügen, haben sie ungefähr die gleiche Größe. Hier habe ich den Befehl \\small nur zur ersten Gleichung hinzugefügt, um den Unterschied zu zeigen.

1
Roberto Canogar

Sie können einfach mathematische Formeln in Android mit dem folgenden Code verwenden.

public void setView(String data,WebView w){
    WebSettings webSettings = w.getSettings();
    webSettings.setJavaScriptEnabled(true);
    String path="file:///Android_asset/v/";
    String js="<html><head>"
       + "<link rel='stylesheet' href='file:///Android_asset/v/jqmath.css'>"
       + "<script src = 'file:///Android_asset/v/jquery-3.0.0.min.js'></script>"
       + "<script src = 'file:///Android_asset/v/jqmath-etc-0.4.3.min.js'></script>"
       + "<script src = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>"
       + "</head><body>"
       + "<script>var s ='"+data+"';M.parseMath(s);document.write(s);</script> </body>";
    w.loadDataWithBaseURL("", js, "text/html", "UTF-8", "");
}
0
Vasant

jqMath ist eine JavaScript-Bibliothek wie MathJax, aber viel kleiner, einfacher und schneller. Wenn Sie nicht alles von LaTeX brauchen, könnte es Ihnen gefallen. Es sollte gut funktionieren auf Android.

Es ist nur ein Vorschlag, ich habe keine Ahnung, welche Fehler oder Vorteile Sie haben könnten, wenn Sie MathJax verwenden.

MathJax ist viel größer und komplizierter als jqMath und ungefähr fünfmal langsamer .

Working JSFIDDLE: http://jsfiddle.net/sinhayash/gWWB5/1/

Für \sqrt{b^2-4ac} können Sie diesen Code haben: √(b^2-4ac)

Sie können die Zeichenfolgenbehandlung in JavaScript ganz einfach verwenden, um Zeichenfolgen in das jqMath-Format zu konvertieren und anzuzeigen

0
sinhayash