Display Good-looking Math Formula in Android
If I understand your problem correctly, it seems the issue is due to the MathJax library has not completed loading (from the loadDataWithBaseURL()
call) when you call the additional loadUrl()
s to display the formula. The simplest fix is to wait for the onPageFinished()
callback to make the call.
For example, the following code seems to work fine on mine:
/** 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: To accommodate additional output in the WebView, I would suggest adding HTML elements to the initial loadDataWithBaseURL()
call. So for the example above, instead of this line at the end:
+ "></script><span id='math'></span>", "text/html", "utf-8", "");
We can do something like the following:
+ "></script><span id='text'>Formula:</span>"
+ "<span id='math'></span>", "text/html", "utf-8", "");
Additionally, if you need to update that part interactively afterward, you can use the same mechanism that we used for the "math" part, something like:
w.loadUrl("javascript:document.getElementById('text').innerHTML='"
+ newText + "';");
You can also use other HTML elements (instead of the <span>
that we use above) if you want to have specific styling/formatting.
Instead of using javascript and javascript libraries to render the LaTeX client-side, why not do the following?
Write a server-side function that takes some LaTeX string and produces an image file. You can do this with the "out of the box" standard LaTeX command line tool. (It seems like this is something you're capable of doing, and that the problem is in getting the rendering to take place client-side.)
Create an endpoint on your web site/service that looks like the following:
GET /latex?f={image format}&s={latex string}
On your web pages, use a simple HTML
<img/>
tag to render your LaTeX. For example:<img src="/latex?f=jpeg&s=f%40x%41%61x%942"/>
will render thef(x)=x^2
equation as a JPEG.(optional) Create a simple server-side cache for
(f,s)
pairs so that you only render a particular LaTeX string on the first request ever made for that particular string (by any client). As a first prototype, you could just have a server directory in which you have files named{hash(s)}.{f}
, wherehash
is just some hash function likeSHA1
.
This relieves you from trying to make everything work client-side with javascript. And, I would argue (although some may disagree), that this is a lot cleaner. All you're sending to the client is:
- the HTML
<img/>
tag - the actual image contents when the browser resolves the
src
attribute
Very lightweight and fast!
The "capital A" problem is a konwn bug of MathJax on Android WebView. You can replace the font files with tweaked font files. The fix will work when using HTML-CSS output with TeX-fonts. Besides MathJax, you can try KaTeX, which is less beautiful but faster.
Actually I've packed them both into an Android custom view, have a look on MathView
.