web-dev-qa-db-ja.com

見栄えの良い数式をAndroid

Androidプラットフォームで科学と数学が十分に注目されていないのを見るのは悲しいことです。これは簡単な問題かもしれませんが、私は完全な男ですjavascriptであるため、この問題を解決する方法を理解するのに苦労しています。

私がやりたいことは簡単です:私はただレンダリング数学方程式を使う必要があります。それは、MathJaxまたはJqMath、あるいは小さくて速いものなら何でもかまいません。 Webビューで実行する必要がある場合、同じWebビュー内でプレーンテキストを段落に表示し、数式をフォーマットするにはどうすればよいですか?

(誰もが明らかに機能する他の方法を思い付きます、私はそれも解決策と見なします)

私がしたことSO FAR:

私はMathJaxを使用して数式をWebビューに配置することから始めました(成功した​​jqMathのユースケースがあるかどうかはわかりませんか?経験を共有したい人はいますか?)すべての機能を再現できますスタンドアロンの場合と同じように MathJax App 。そのアプリでは、ユーザーがEditTextフィールドに文字列を入力すると、ユーザーがボタンを押して確認すると、MathJaxはLaTeXで数式をレンダリングします。

ユーザーが確認する必要はありません。ユーザーの操作がないので、これは簡単なはずだと思いましたが、どういうわけか方程式が表示されません。スタンドアロンのMathJaxのコードはユーザー入力用であるため、何かが足りないに違いないことはわかっています。文字列から方程式を直接レンダリングするには、コードのどの部分を変更する必要がありますか?たとえば、\ sqrt {b ^ 2-4ac}? webviewの最初のヘッダーは次のとおりです。

_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","");
_

そして、ユーザーがテキストを編集するために入力した後にボタンを押したときに、元のWebビューがどのように読み込まれるかを次に示します。

_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;
}
_

ハードコードされた文字列に置き換えようとしました

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

しかし、それは機能しません。テキスト_"sample string"_はWebビューにも表示されません。

[解決策]ジョーの答えを参照

彼の答えを詳しく説明するために、これはプレーンテキストで文を設定し、フォーマットされた方程式を表示形式で表示する方法の例です(すべて単一のWebビューで):

上記の最後の行をで置き換えます

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

_+"></script><span id='text'>This is plain text.</span> <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("\\sqrt{b^2-4ac}") + "\\\\]';");
        w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
    }
});
_

これにより、文字列が設定されますこれは通常のフォントのプレーンテキストであり、数式を中央に表示します foo+bar webviewで。

編集(Android 4.4の問題)

Android KitKatから、すべての行loadUrl(...)evaluateJavascript(...)に置き換える必要があります。ただし、これはKitKat(API 19以降)でのみ使用できます。 、したがって、最初にSDKバージョンチェックを実行する必要があります。例:

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

更新(MATHJAX 2.5以降)

フォルダが変更されているため、以前のコードは最新バージョンのMathJaxでは機能しません。さらに、ローカルMathJaxのサイズを最小化するための推奨される方法は、現在 Grunt を使用しています。 MathJaxのサイズを縮小するためのテンプレートは ここ にあります。

MathJaxのサイズを正常に縮小し、HTML-CSSの出力を想定すると、MathJaxをロードできる単純なバージョンを次に示します。

_@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);
            }
        }
    });
}
_

Joesの回答とは異なり、テキストや数学の種類を分ける必要はありません。MathJaxはそれに応じてフォーマットするだけです。

ただし、キットカットデバイスのWebビューで大文字の「A」を表示できないというバグがあるようです。方法を知っている人は誰でもこれの回避策を提供することを歓迎します。

28
Neoh

私があなたの問題を正しく理解している場合、問題は、式を表示するために追加のloadDataWithBaseURL() sを呼び出したときに、MathJaxライブラリが(loadUrl()呼び出しから)ロードを完了していないことが原因であると思われます。最も簡単な修正は、onPageFinished()コールバックが呼び出しを行うのを待つことです。

たとえば、次のコードは私のものではうまく機能しているようです。

_/** 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]);");
        }
    });
}
_

更新:WebViewでの追加出力に対応するために、最初のloadDataWithBaseURL()呼び出しにHTML要素を追加することをお勧めします。したがって、上記の例では、最後のこの行の代わりに:

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

次のようなことができます。

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

さらに、後でその部分をインタラクティブに更新する必要がある場合は、「数学」部分に使用したのと同じメカニズムを使用できます。たとえば、次のようになります。

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

特定のスタイル/フォーマットが必要な場合は、(上記で使用した_<span>_の代わりに)他のHTML要素を使用することもできます。

21
Joe

Javascriptおよびjavascriptライブラリを使用してLaTeXクライアント側をレンダリングする代わりに、次のことを行ってみませんか?

  1. LaTeX文字列を受け取り、画像ファイルを生成するサーバー側関数を記述します。これは、「すぐに使える」標準のLaTeXコマンドラインツールを使用して実行できます。 (これはあなたができることのようであり、問​​題はレンダリングをクライアント側で実行することにあるようです。)

  2. 次のようなエンドポイントをWebサイト/サービスに作成します。
    _GET /latex?f={image format}&s={latex string}_

  3. Webページで、単純なHTML _<img/>_タグを使用してLaTeXをレンダリングします。例えば:
    _<img src="/latex?f=jpeg&s=f%40x%41%61x%942"/>_
    f(x)=x^2方程式をJPEGとしてレンダリングします。

  4. (オプション)_(f,s)_ペア用の単純なサーバー側キャッシュを作成して、特定の文字列に対して(任意のクライアントによって)行われた最初の要求でのみ特定のLaTeX文字列をレンダリングするようにします。最初のプロトタイプとして、{hash(s)}.{f}という名前のファイルがあるサーバーディレクトリを作成できます。ここで、hashは_SHA1_のようなハッシュ関数です。

これにより、JavaScriptを使用してすべてをクライアント側で機能させようとする必要がなくなります。そして、私は(一部の人は同意しないかもしれませんが)これははるかにクリーンであると主張します。クライアントに送信するのは次のとおりです。

  1. hTML _<img/>_タグ
  2. ブラウザがsrc属性を解決するときの実際の画像コンテンツ

非常に軽量で高速です!

5
Timothy Shields

「大文字のA」の問題は、Android WebViewでのMathJaxの既知のバグです。フォントファイルを 微調整されたフォントファイル に置き換えることができます。この修正はHTMLを使用する場合に機能します。 -TeXフォントを使用したCSS出力。MathJaxの他に、 KaTeX を試すことができます。これは、それほど美しくはありませんが、高速です。

実際、私は両方をAndroidカスタムビューにパックしました。 MathView を見てください。

2
kexanie

パーティーに遅れましたが、私はジョーよりも良い解決策があると思います。元の質問は次のとおりです。

同じWebビュー内でプレーンテキストを段落に表示し、数式をフォーマットして表示するにはどうすればよいですか?

元の例では、次のようになりました。

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

_\\\\[_と_\\\\]_に気づきましたか?これらの4つの円記号は、LaTeXによって1つだけとして解釈され、LaTeXの_\[_および_\]_ の省略形 _\begin{equation}... \end{equation}_は、表示される数学のブロックを生成します。段落内にいくつかの方程式を含むテキストの段落が必要な場合は、_\\\\[_を削除し、LaTeXコマンド_\(_および_\)_を使用する必要があります。段落数学と表示された数学の例のコードは次のようになります。

_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}. \\]"
    )+"';");
_

WebViewは次のようになります。 enter image description here ノート:

  • 必要なバックスラッシュは4つではなく2つだけです。これは、doubleEscapeTeX()内にあり、この関数がバックスラッシュを複製しているためです。

  • また、数学環境外のテキストはHTMLでレンダリングされます(_<span id='math'>_タグ内)。

  • LaTeXフォントはhtmlフォントよりも大きいため、各数学環境に_\\small_を追加すると、ほぼ同じサイズになります。ここでは、違いを示すために、最初の式にのみ_\\small_コマンドを追加しました。

1
Roberto Canogar

以下のコードを使用して、Androidで数式を簡単に使用できます。

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はMathJaxのようなJavaScriptライブラリですが、はるかに小さく、単純で、高速です。LaTeXのすべてが必要ない場合は、それをお勧めします。 Androidでは正常に動作するはずです。

これは単なる提案であり、MathJaxを使用した場合にどのようなエラーや利点があるのか​​わかりません。

MathJaxはjqMathよりもはるかに大きく複雑であり、約5倍遅くなります

作業中のJSFIDDLE: http://jsfiddle.net/sinhayash/gWWB5/1/

_\sqrt{b^2-4ac}_の場合、次のコードを使用できます:√(b^2-4ac)

Javascriptで文字列処理を簡単に使用して、文字列をjqMath形式に変換し、簡単に表示できます。

0
sinhayash