讓Android支援Latex數學公式

cedear發表於2019-03-11

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公式時所有的操作,希望在別人遇到這個問題的時候能有所幫助。

相關文章