IconFontPreview——一款預覽IconFont的外掛

Drowning Coder發表於2019-02-25

背景

使用過IconFont的應該都深有體會,每次使用IconFont的時候,由於不知道Unicode和Icon的對應關係,每次都要到對應的資料夾下找到預設生成的html檔案,開啟後才能尋找到我們需要的IconFont。而每次找檔案這個過程真的很麻煩,而且當公司IconFont的版本更新的時候,這個路徑也會相應改變,那就更痛苦了。 為了解決這個問題,我就考慮能不能做一款預覽IconFont的外掛,避免這種痛苦的尋找檔案過程,提高開發效率。

功能特性

  • 支援已定義的IconFont的預覽
  • 支援快取避免每次查詢
  • 使用方便

原始碼地址

IconFontPreview

歡迎Star?~ 歡迎提issue和PR~ 這裡再推薦一下我的另一個開源專案EasyTextView,一款高效利用IconFont的TextView,功能豐富,用過的人都說好~

jar包地址

我已經發布到Intellij的官網上了,不知道為啥搜不到

IconFontPreview.zip

使用步驟

1.安裝完外掛後,在操作皮膚會生成一個草帽的Icon,點選操作面版的草帽icon(ONE PIECE)

step1

2.第一次需要設定工程下ttf字型檔案路徑和定義iconfont的string.xml路徑

step2.jpg

這一步只會在第一次才會使用,因為本地會有快取,後面的會讀取快取的目錄(根目錄下的PlugCache)

3.點選確定後或者以後在點選草帽就會在瀏覽器中開啟預覽定義的IconFont圖示了

ONE PIECE

4.後面再使用就可以直接點選操作皮膚的草帽Icon就會直接彈出預覽頁面了

實現原理

1.IntelliJ外掛開發

這個網上部落格很多,這裡就不專門講解了

2.XML解析

這裡本來一開始是準備直接讀取ttf檔案,然後直接生成ttf檔案中所有定義的IconFont的,但是我好像沒有找到實現方式(大家有好的實現方式可以告訴我~,或者提PR) 我們一般定義IconFont的都會在String.xml定義unicode類似於下面

<resources>
    <!--後退-->
    <string name="icon_font_606">\ue606</string>
    <!--評論-->
    <string name="icon_font_comment">\ue68f</string>
    <!--收藏-->
    <string name="icon_font_collection">\ue68e</string>
    <!--贊-->
    <string name="icon_font_like">\ue695</string>
</resources>
複製程式碼

所以這裡就需要我們遍歷XML了,這裡我選擇了SAX解析的方式,取出了定義的Key,和對應的Unicode,並儲存起來

3.Jsoup動態渲染HTML

拿到我們的資料集後,我們就需要生成我們最終的預覽頁面了,這裡直接利用IconFont固定的HTMl模版,下載下來,利用Jsoup這個HTMl解析庫,遍歷我們生成的資料集,並對應在固定位置插入HTML程式碼,最後利用File儲存到PluginCache資料夾下 這裡有幾個問題:

3.1 jar包中HTML讀取css檔案路徑問題

由於外掛最終生成的是jar檔案,所有html中的css檔案,由於路徑無法讀取,需要將css檔案拷貝到html中

3.2 快取檔案需要利用檔案流儲存,這裡涉及到外掛的資料持久化。

因為使用者設定的ttf檔案路徑和string.xml檔案路徑不能每次點選都要重新設定,哪還要這個外掛幹啥...,所以我就想將使用者設定的這兩個路徑快取起來,所以這裡就涉及到外掛的資料持久化。 網上提供的外掛持久化的兩種方式我都試了一下,發現沒法真正意義上的持久化,當你idea關閉後,這些資料都會被對應清理掉,對應於 1.使用PersistentStateComponent 2.使用PersistentStateComponent 所以最後我是用了檔案流的方式快取目錄路徑(大家如果有更好的方式可以告訴我~)

/**
     * 建立li
     */
public static final String ICON_ITEM = "<li>\n" +
            "                <i class=\"icon iconfont\">%s</i>\n" +
            "                    <div class=\"name\">%s</div>\n" +
            "                    <div class=\"code\">%s</div>\n" +
            "                </li>";
public void printer(String ttfPath) {
        InputStream html = this.getClass().getResourceAsStream(Common.HTML_PATH);
        try {
            Document doc = Jsoup.parse(html, "UTF-8", "");
            if (data != null) {
                Elements style = doc.select("style");
                style.prepend(String.format(Common.STYLE_DF, ttfPath));
                Elements container = doc.getElementsByClass("icon_lists clear");
                if (Common.MODE_ALL) {
                    //全量模式,從16進位制最小值到16進位制最大值
                    printerAll(container);
                } else {
                    //自定義模式,只輸出定義的資原始檔
                    printerDefine(container);
                }
            }
            File result = CreateFileUtil.createFile(RESULT_PATH);
            if (result == null) {
                return;
            }
            FileOutputStream outStream = new FileOutputStream(result);    //檔案輸出流用於將資料寫入檔案
            outStream.write(doc.toString().getBytes(StandardCharsets.UTF_8));
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void printerDefine(Elements container) {
        for (Map.Entry<String, XmlIconFontModel> entry : data.getFonts().entrySet()) {
            String code = entry.getValue().getFontValue();
            if (code.startsWith(Common.ICON_START)) {
                String value = "&#xe" + code.substring(3) + ";";
                container.append(String.format(Common.ICON_ITEM, value,
                        entry.getValue().getFontKey(), code));
            } else if (code.startsWith(Common.ICON_START_SUB)) {
                container.append(String.format(Common.ICON_ITEM, code,
                        entry.getValue().getFontKey(), code));
            }
        }
    }
複製程式碼

4.利用exec執行命令,開啟生成的html檔案

/**
         * 執行展示
         */
        try {
            if (OSinfo.isWindows()) {
                Runtime.getRuntime().exec("cmd.exe /c start " + RESULT_PATH);
            } else {
                Runtime.getRuntime().exec("open " + RESULT_PATH);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
複製程式碼

相關推薦

【乾貨】基於iconfont擴充的EasyTextView(高度自定義,豐富Api,支援左右設定Text,設定Shape,設定span等)

EMvp-基於AOP的一種RecyclerView多樓層開發模式,支援元件化,全域性樓層打通,MVP等高擴充性功能

相關文章