編輯:關於Android編程
問題一、android系統支持什麼字體庫?
1、Android系統默認支持三類字體家族,分別為:“serif”,“sans-serif”,“monospace",那如何證明?具體論證與定義詳見下面的知識點。
這三類字體家族,每一類都包括若干個*.ttf的字體文件。除此之外,每個設備廠商在此基礎上,都會額外增加一些自己定義的字體文件*.ttf,以兼容更多的語言及字體風格。
以三星手機(SM-N7508V)為例:這些字體文件總計84個(如下圖)。
問題二、不同設備手機默認獲取的字體是什麼?(以三星(SM-N7508V)手機為例)
在/system/etc/system_fonts.xml文件中有如下描述
也就是說,在沒有指定具體的字體名字的情況下,系統默認使用的字體家族是第一標簽中顯示的字體家族。
一個xml文件中有多個字體家族,而多個字體家族會形成一個鏈表,如果整個鏈表中都沒有某個字體,那麼就在system/ect/fallback_fonts.xml配置文件中去找其他字體的描述。
如果我們想要額外增加或修改字體,則需要在vendor/etc/fallback_fonts.xml文件中進行配置。
代表該font family的名字,一般第一個標簽代表字體家族的名字。表示該font family所對應的*.ttf文件.每個字體家族都可以有normal,
粗體,斜體字,粗斜體等四種樣式。但並不都是必須要有的。從上圖中可以看出,三星(SM-N7508V)這個手機,(結論)優先使用的字體庫為"Roboto-Regular.ttf"、"bold.ttf"、
"italic.ttf"、"Roboto- BoldItalic.ttf"。分別代表正常,粗體,斜體字,粗斜體等四種樣式。三星手機字體庫文件請見附件。
在 system/ect/fallback_fonts.xml文件中有如下描述:
這個文件中再次說明了,如果這個字體家族中沒有某個字體,那麼可以在system/ect/fallback_fonts.xml配置文件中找到其他字體的描述。
思考:那麼這些XML文件是如何解析,字體庫又是如何被初始化的。(請見第三部分<其他相關知識擴充>)。
3、不同手機設備,配置文件是不同的。也就是說,不同的手機,用的字體庫也是不同的。
如VIVO手機(型號X5M): 用的完全是自己的字體庫,如下圖:
4、 我們的H5頁面使用的樣式字體為:SimHei
當手機浏覽器在手機系統中能找到SimHei,則使用SimHei;找不到這個SimHei時,默認會選擇手機系統中默認字體。
相關知識點:
a、Serif的意思是,在字的筆劃開始及結束的地方有額外的裝飾,而且筆劃的粗細會因直橫的不同而有不同。相反的,SansSerif則沒有這些額外的裝飾,筆劃粗細大致差不多
Serif和SansSerif的一般比較
1)Serif的字體容易辨認,因此易讀性較高。反之SansSerif則較醒目,但在行文閱讀的情況下,SansSerif容易造成字母辨認的困擾,常會有來回重讀及上下行錯亂的情形。
2)Serif強調了字母筆劃的開始及結束,因此較易前後連續性的辨識。
3)Serif強調一個word,而非單一的字母,反之SansSerif則強調個別字母。
4)在小字體的場合,通常SansSerif比Serif更清晰。
5)可以看出,我們平時所用的Georgia、TimesNewRoman等就屬於Serif字體,而Arial、Tahoma、Verdana等則屬於SansSerif字體。
對中文而言,同樣存在這兩大種類,很明顯,宋體、細明體(繁體中常用)等就屬於Serif,而黑體、幼圓等則屬於SansSerif。
b、Monospace:等寬字體,它是指每個字符寬度都一致的字體。一個著名的例子就是CourierNew字體。因為字符寬度一致,所以這種字體特別容易對齊,
能快速精確的定位到某行某列,因此經常用來顯示代碼
二、問題二:關於全角半角的問題?
1、漢字:不管全角還是半角,漢字要占用兩個字節。
2、數字與字母:半角與全角都是一個字節
3、標點符號:半角情況下(一個字節),全角情況下(兩個字節)
三、相關知識擴充
1、通過試驗,三星手機的字體編碼使用的是ISO8859-1。在這種編碼下,中文占二個字節。其他手機(已測試的VIVO,華為,小米)使用的是utf-8編碼,
這種編碼是動態的,1-4個字節不等。中文一般占三個字節。
2、如果需要自定義字體的話,android.graphics.Typeface提供了3個API供應用程序創建特定字體:
a、 Typeface createFromAsset(AssetManager mgr, String path);
b、Typeface createFromFile(File path);
c、Typeface createFromFile(String path);
以及如下3個API來創建系統字體:
a、Typeface create(String familyName, int style);
b、Typeface create(Typeface family, int style);
c、Typeface defaultFromStyle(int style);
3、如何證明android默認包括這三類字體呢?system/ect/fallback_fonts.xml和/system/etc/system_fonts.xml文件是如何被解析的,字體庫又是如何被初始化的?
往framework層去看,在如下路徑下frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。這個ZygoteInit類中的preloadClasses方法是加載字體庫的入口
具體過程如下:
Zygote preloadClasses() -> Class.forName("android.graphics.Typeface")–> 執行Typeface.javastatic塊 -> Typeface.cpp Typeface_create–> SkTypeface.cpp CreateFromName() -> SkFontHost.cpp load_system_fonts()
我們先看android.graphics.Typeface這個類
static { DEFAULT = create((String)null,0); DEFAULT_BOLD = create((String)null, Typeface.BOLD); SANS_SERIF = create("sans-serif", 0); SERIF =create("serif", 0); MONOSPACE= create("monospace", 0);//從這裡可以看出JAVA層面默認創建三類字體 sDefaults = newTypeface[] { DEFAULT, DEFAULT_BOLD, create((String)null, Typeface.ITALIC), create((String)null, Typeface.BOLD_ITALIC), }; public static Typeface create(String familyName, int style) { return newTypeface(nativeCreate(familyName, style)); } nativeCreate()是jni方法,調用C++層的Typeface.cpp方法,在這個方法中,有一種數據結構(如下),它對應著/system/etc/system_fonts.xml文件中的每個family標簽 struct FontFamily { SkTDArray fNames;//保存標簽對應的名字 SkTDArrayfFileNames;//保存了標簽對應的文件名 int order;//每個字體家族的加載順序 };
還有其他的一些的數據結構,就不在這列舉啦!
........................省略中間的代碼......................................
最終會調用到C++層的SkFontHost.cpp中的load_system_fonts()方法完成字體加載。
4、(注意)字庫大部分都是有版權的,所以你看到Android手機中很少有字體選擇功能,即使有的話,那麼一般都是鏈接到自己定義的字體庫上。
之前在技術問答上面看到一個提問 “加載中…” 後面三個點是動態的,這麼一個效果實現。想來想去,好像沒想到好的處理方式。 嘗試了一下,以一個最笨的方式實現了。先來看一下效果
每次應用程序運行時,應用程序的application類保持實例化的狀態。通過擴展applicaiton類,可以完成以下3項工作: 1.對android運行時廣播的應用程序
BroadcastReceiver,顧名思義就是“廣播接收者”的意思,它是Android四大基本組件之一,這種組件本質上是一種全局的監聽器,用於監聽系統全局的廣播消息。它
一、Canvas Canvas中的方法很多,這裡我們只挑常用的進行講解說明 Canvas可以繪制的對象有: 弧線(arcs) canvas. 填充顏色(argb和co