让Android支持Latex数学公式

3,049 阅读3分钟

LaTeX(LATEX,音译“拉泰赫”)是一种基于ΤΕΧ的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在20世纪80年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由TeX所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。这个系统同样适用于生成从简单的信件到完整书籍的所有其他种类的文档。

以上是“百度百科”对Latex的解释,由于需求要求,现在需要实现功能,在App中展示Latex公式。当然了,普通的Textview肯定是不到要求的,如果服务器传给我们的是这种原生的公式,那就只能是左边这种看不懂的东西了,所以需要某种方式来达到目的,让我们看懂,像右边的这样。

image

经过多方寻找,我们找到了最终的解决方案---MathJax.js

MathJax.js能够使页面上的我们看不懂的这种公式转换成我们看懂的公式,沿着这个线索,我们继续探索。既然用到了js,那么就需要有承载js的载体,在Android中只能是Webview了,所以在该功能中,我们将所有展示数学公式的地方都用Webview来展示,并且用MathJax.js来解析其中的公式并最终展示给我们想要的、能够看懂的公式形式。

实现思路

使用Webview加载本地的一个配置有MathJax.js的html文件,并调用js方法动态替换公式展示区域的公式,就这么简单!

本地的html文件如下:

注意放在assets文件夹下,随意取个名字就可以,我取名就叫MathJax.html了。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script type="text/x-mathjax-config">
            MathJax.Hub.Config({
                messageStyle: "none",tex2jax:
                    {inlineMath: [ ['$','$'], ["\\(","\\)"] ],
                    displayMath: [ ['?','?'], ["\\[","\\]"] ]},
                });
    </script>
    
    <script>
        function changeData(data) {
            document.getElementById('mainDiv').innerHTML = data;
            MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
        }
    </script>
    <script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>
    <style type="text/css">
            body{
                background-color: #ffffff;
                -webkit-text-size-adjust: 100%!important;
                -webkit-overflow-scrolling : touch;
            }
            #mainDiv{
                position: absolute;
                margin: auto;
                width: 100%;
                height: 100%;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                font-size: 15px;
                word-wrap:
                break-word;
            }
        </style>
</head>

<body>
<div id="mainDiv">
</div>
</body>
</html>

以上html的内容都是参考MathJax.js的官网及自己项目需要所配置的,在第一个script片段中配置的是MathJax.js的公式过滤规则,第二个script片段是我自己实现的一个js方法,用来动态替换显示区域的公式,并调用
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
通知MathJax.js去重新渲染页面,否则不会生效。

Webview的相关设置

我们可以动态生成一个Webview,也可以在xml中画一个Webview,然后设置相关属性,并调用js方法将公式加载到webview中显示出来我们想要的样子。

        container = "已知集合\(A=\{-1,1\}\),\(B=\{x|mx=1\}\),且\(A\cup B=A\),则\(m\)的值为________"
        webView = findViewById(R.id.webview);
        mWebSettings = webView.getSettings();
        //支持与JS交互
        mWebSettings.setJavaScriptEnabled(true);
        //设置编码格式
        mWebSettings.setDefaultTextEncodingName("utf-8"); 
        //设置webview的页面监听
        webView.setWebViewClient(new WebViewClient() {
            
            @Override
            public void onPageFinished(final WebView view, String url) {

                //访问JS方法
                webView.loadUrl("javascript:changeData('" + contain + "')");

            }
            
        }); 
        webView.loadUrl("file:///android_asset/MathJax.html");

我们想要的结果:

image

但是实际的结果:
image

惊不惊喜?意不意外?怎么不好使了呢?在排查了一遍又一遍之后,又经过大佬得细节排查,学会了一个新知识-----“调用js传参的时候,会将'\'这个符号转义,这也怪自己才疏学浅了。再发现问题后,在每一个出现'\'的地方转成'\\'”,这样就解决了问题,将正确的公式传到了webview,MathJax.js才将正确的公式解析成我们想要的样子。

以上就是我在做webview支持Latex公式时所有的操作,希望在别人遇到这个问题的时候能有所帮助。