目前項(xiàng)目中使用ttf圖標(biāo)庫(kù),來(lái)展示一些app里的小圖標(biāo)黄痪。ttf文件小紧帕,且Android,IOS桅打,與H5之間可以共用一份ttf文件是嗜,具備一定的優(yōu)點(diǎn)。下面介紹下在android項(xiàng)目中的使用方法挺尾,以及碰到的編碼問(wèn)題
目前項(xiàng)目采用的ttf圖標(biāo)生成工具地址為:https://icomoon.io/app,最終提供給開(kāi)發(fā)人員的文件是“文件名.ttf”鹅搪。
ttf使用方法
- Android開(kāi)發(fā)人員將ttf文件放在assets文件夾下。
- 通過(guò)以下代碼為顯示ttf圖標(biāo)的TextView設(shè)置字體庫(kù)遭铺。
Typeface typeface = Typeface.createFromAsset(context.getAssets(), name);
textView.setTypeface(typeface);
上面是實(shí)例代碼丽柿,實(shí)際開(kāi)發(fā)中可根據(jù)需要進(jìn)行優(yōu)化。一種是通過(guò)自定義View繼承AppCompatTextView掂僵,該View在構(gòu)造時(shí)即設(shè)置字體庫(kù)航厚。且字體庫(kù)也可考慮做全局唯一緩存。還有一種是想到全局設(shè)置字體的方案锰蓬,可通過(guò)LayoutInflater.setFactory實(shí)現(xiàn)幔睬。方法可參考文檔LayoutInflater.setFactory學(xué)習(xí)及進(jìn)階。
- 查看ttf文件對(duì)應(yīng)的圖標(biāo)編碼芹扭,并將其在string.xml進(jìn)行定義麻顶。
圖標(biāo)編碼
針對(duì)上圖中的編碼,string定義如下舱卡。注意編碼必須使用\u前綴指定編碼為Unicode辅肾。
<string name="ic_eye_open_small">\ue943</string>
- 代碼中為TextView設(shè)置該ttf圖標(biāo)編碼
textView.setText(R.string. ic_eye_open_small);
編碼問(wèn)題
使用中遇到到一些編碼問(wèn)題,在此記錄下轮锥。同時(shí)也必須感慨基礎(chǔ)知識(shí)的重要性矫钓,以及遇到不理解的解決方案時(shí)必須要有一顆“知其所以然”的恒心。
\u編碼長(zhǎng)度
\u指定了字符的編碼格式為Unicode,目前Java中表示的是UTF-16新娜,也即必須有2個(gè)字節(jié)來(lái)存儲(chǔ)Unicode編碼赵辕。
ttf圖庫(kù)中的編碼為ui人員在ttf文件生成時(shí)同時(shí)產(chǎn)生的,且可變更ttf圖標(biāo)的編碼概龄。這里我們就犯過(guò)一個(gè)錯(cuò)誤还惠,定義了e9400,e9411這種非2個(gè)字節(jié)的編碼。在string.xml中使用該編碼時(shí)私杜,最終getString獲取的內(nèi)容為""蚕键。
同時(shí)參考Unicode規(guī)范,推薦圖標(biāo)編碼使用Private Use Area區(qū)域的編碼衰粹。
\u編碼問(wèn)題
前期在Android項(xiàng)目?jī)?nèi)通過(guò)string.xml中定義锣光,引用R.string.ttf_icon_name,一直沒(méi)有遇到問(wèn)題寄猩,但是在H5向Android傳遞具體編碼時(shí)出現(xiàn)了問(wèn)題嫉晶。
因H5端字符集編碼的不同,Android收到的入?yún)⒅挥小癳943”字符串田篇。我天真的以為拼上\u就可以完成任務(wù)了替废,但是測(cè)試過(guò)程并不順利。
textView.setText(R.string. ic_eye_open_small); //OK
textView.setText("\ue943"); //OK
String text = "\ue943";
texView.setText(text);//OK
String erroText = "\\u" + "e943";
texView.setText(text);//FAIL
根據(jù)上面的測(cè)試過(guò)程泊柬,我們可猜測(cè)Java僅僅將字符串常量"\uXXXX"進(jìn)行翻譯椎镣。但是"\u" + "e943"這種最終只是得到一個(gè)存儲(chǔ)字符u,e,9,4,3的字符串。所以需要提取e943對(duì)應(yīng)的int并轉(zhuǎn)為char兽赁,再通過(guò)char拼裝String即可状答。
String text = "";
String arr = "e943";
int hexVal = Integer.parseInt(arr, 16);
text += (char)hexVal;
具體我也沒(méi)完全理解上面代碼生效的原因,實(shí)際嘗試各種轉(zhuǎn)Unicode方法均沒(méi)有成功刀崖【疲可能與char存儲(chǔ)的不是字符,而是存放字符對(duì)應(yīng)的編號(hào)有關(guān)吧亮钦。
還有一種解決方法可以嘗試馆截。
String text = "";
Html.fromHtml(text);
“java中有個(gè)基本類型char,它占用固定的2byte空間來(lái)表示字符蜂莉,又因?yàn)閖ava設(shè)計(jì)之初就采用了Unicode編碼蜡娶,所以char能表示所有字符包括中文∮乘耄”
--- Thinking in java
char類型賦值
根據(jù)下面的char賦值規(guī)律窖张,可以理解上面方法生效的原因。
char a=’a’; //任意單個(gè)字符蚁滋,加單引號(hào)宿接。
char a=’中’;//任意單個(gè)中文字赘淮,加單引號(hào)。
char a=111;//整數(shù)睦霎。0~65535拥知。十進(jìn)制、八進(jìn)制碎赢、十六進(jìn)制均可。輸出字符編碼表中對(duì)應(yīng)的字符
參考文檔:
IconFont的制作及在Android的使用
IconFont使用文檔
https://stackoverflow.com/questions/11145681/how-to-convert-a-string-with-unicode-encoding-to-a-string-of-letters
https://stackoverflow.com/questions/28368856/how-to-convert-string-into-unicode-in-android
https://developer.android.com/guide/topics/resources/string-resource#FormattingAndStyling
Java中char型變量存放的是字符嗎速梗?
Java中char和String 的深入理解 - 字符編碼