Android自定義字體設(shè)置
1.typeface、fontFamily、textStyle介紹
1.typeface 字體
typeface 枚舉類型碱璃,值如下
- normal(默認(rèn)字體)
- sans (無襯線字體)
- serif(有襯線字體)
- monospace(等寬字體)
sans 和 serif 介紹:
在西方國家羅馬字母陣營中,字體分為兩大種類:Serif和Sans Serif。
serif(有襯線字體):在字的筆劃開始及結(jié)束的地方有額外的裝飾作岖,而且筆劃的粗細(xì)會(huì)因直橫的不同而有不同。
sans serif(無襯線字體):沒有額外的裝飾五芝,筆劃粗細(xì)大致差不多
monospace 介紹:
打字機(jī)體雖然也屬于Sans Serif痘儡,但由于是等寬字體,所以另外獨(dú)立出Monospace這一種類
monospace (等寬字體):指每個(gè)字符寬度都一樣枢步。優(yōu)點(diǎn)容易對(duì)齊谤辜,經(jīng)常用來顯示代碼。
2.fontFamily 字型家族
什么是字型家族价捧?它和typeface 的區(qū)別丑念?要想了解首先得了解下什么是 typeface、font
typeface:字體结蟋,是一個(gè)抽象的總體概念(它是一款“設(shè)計(jì)”)脯倚,例如:宋體、楷體
font:是指特定尺寸、特定字重推正、字偶間距等信息的一種 Typeface 的具體實(shí)現(xiàn)
fontFamily 是font的一個(gè)集合
使用提示可知 fontFamily 值如下
- sans-serif
- sans-serif-condensed
- sans-serif-smallcaps
- serif
- serif-monospace
- monospace
- casual
- cursive
3.textStyle 字體樣式
textStyle 標(biāo)記類型恍涂,值如下
- normal(默認(rèn)字體)
- bold (加粗)
- italic(斜體)
4.三者關(guān)系
查看TextView源碼(API 27)可知:TextView構(gòu)造方法大致如下
public TextView(Context context,AttributeSet attrs,int defStyleAttr,int defStyleRes) {
...
setTypefaceFromAttrs(fontTypeface, fontFamily, typefaceIndex, styleIndex);
...
}
setTypefaceFromAttrs方法
/**
*
* @param fontTypeface 要設(shè)置的 Typeface
* @param familyName 要設(shè)置的 fontFamily
* @param typefaceIndex 要設(shè)置的 typeface
* @param styleIndex 要設(shè)置的 style
*/
private void setTypefaceFromAttrs(Typeface fontTypeface,String familyName,
int typefaceIndex,int styleIndex) {
Typeface tf = fontTypeface;
if (tf == null && familyName != null) {
// 有fontFamily時(shí),用fontFamily
tf = Typeface.create(familyName, styleIndex);
} else if (tf != null && tf.getStyle() != styleIndex) {
tf = Typeface.create(tf, styleIndex);
}
if (tf != null) {
setTypeface(tf);
return;
}
switch (typefaceIndex) {
case SANS:
tf = Typeface.SANS_SERIF;
break;
case SERIF:
tf = Typeface.SERIF;
break;
case MONOSPACE:
tf = Typeface.MONOSPACE;
break;
}
// 其它都用typeface
setTypeface(tf, styleIndex);
}
總結(jié):
1.typeface植榕、fontFamily:都是設(shè)置字體再沧,都設(shè)置時(shí)優(yōu)先使用 fontFamily。
2.textStyle:設(shè)置字體的樣式
2.設(shè)置自定義字體
方式1:直接設(shè)置
1.把字體ttf文件放到assets/fonts目錄下尊残,沒有此目錄手動(dòng)創(chuàng)建
2.設(shè)置
Typeface typeface = Typeface.createFromAsset(getAssets(), "fonts/aa.ttf");
textView.setTypeface(typeface);
3.優(yōu)化
使用優(yōu)化:繼承自TextView炒瘸,重寫getTypeface(),返回自定義typeface
typeface創(chuàng)建優(yōu)化:可用map封裝后進(jìn)行獲取寝衫,代碼略
Override
public Typeface getTypeface() {
return Typeface.createFromAsset(getContext().getAssets(), "fonts/aa.ttf");
}
總結(jié):
適用于:指定TextView
方式2:反射設(shè)置
1.把系統(tǒng)的typeface替換為自定義的
Typeface typeFace = Typeface.createFromAsset(getAssets(), "fonts/aa.ttf");
try {
// xml屬性值與Typeface屬性值對(duì)應(yīng)
// normal Typeface.DEFAULT
// sans Typeface.SANS_SERIF
// serif Typeface.SERIF
// monospace Typeface.MONOSPACE
Field field = Typeface.class.getDeclaredField("SERIF" );
field.setAccessible( true);
field.set( null, typeFace );
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
2.設(shè)置typeface值為 sans顷扩、 serif、 monospace其中一種慰毅,可在TextView隘截、Activity、Application里面的xml樣式里面設(shè)置
android:typeface="serif"
原理介紹:
1.xml設(shè)置完typeface為指定值后汹胃,最終xml會(huì)解析為代碼執(zhí)行(例如:設(shè)置android:typeface="serif"
最終會(huì)解析調(diào)用setTypeface(Typeface.SERIF))
2.預(yù)先把Typeface的某個(gè)系統(tǒng)字體通過反射強(qiáng)制替換自定義的Typeface(例如:把Typeface.SERIF強(qiáng)制替換為自定義的字體)
3.xml中設(shè)置typeface為已替換的字體即可(例如:android:typeface="serif")
舉例說明:例如:xml設(shè)置字體android:typeface="serif"婶芭,代碼設(shè)置的字體是Typeface.SERIF,可是Typeface.SERIF里面的內(nèi)容是強(qiáng)制替換后的自定義的字體
總結(jié):
適用于:App字體樣式不多的情況着饥,因?yàn)槟隳芴鎿Q的就SANS_SERIF犀农、SERIF、MONOSPACE這幾個(gè)值
方式3:fontFamily設(shè)置
1.把字體ttf文件放到res/fonts目錄下贱勃,沒有此目錄手動(dòng)創(chuàng)建或使用Android studio創(chuàng)建
2.設(shè)置
1.TextView設(shè)置
android:fontFamily="@font/aa"
2.activity井赌、application樣式里設(shè)置
<item name="android:fontFamily">@font/aa</item>
3.兼容
因?yàn)?fontFamily API16 新增,所以要使用低版本的兼容庫 com.android.support:appcompat-v7:26.0.0 以上
1.TextView設(shè)置
app:fontFamily="@font/aa"
2.activity贵扰、application樣式里設(shè)置
<item name="fontFamily">@font/aa</item>
總結(jié):
適用于:各種情況
Demo github地址: devblog androidFont
3.設(shè)置下載字體(了解)
為什么要下載字體:最主要的原因就是可以減少apk的體積仇穗,因?yàn)樽煮w放到apk內(nèi)會(huì)增大apk體積,通過下載就不會(huì)戚绕。
使用范圍:此功能是Android 8.0(API26)新增纹坐,但是兼容庫已兼容到API14,所以可放心使用
原理:所有的app都可以從字體提供app(例如:Google Play Services)里獲取字體舞丛,字體提供app會(huì)把字體緩存到本地耘子,所以如果多個(gè)app用相同的字體,它們則會(huì)共用同一個(gè)字體文件球切,優(yōu)點(diǎn):減少手機(jī)內(nèi)存和磁盤空間谷誓,提高整體系統(tǒng)的運(yùn)行狀況。
使用前提:手機(jī)上必須有一個(gè)字體提供app吨凑,目前了解的國內(nèi)沒有捍歪,國外的只有Google Play Services(版本11及以上)户辱,由于目前國內(nèi)很少安裝Google Play Services,所以國內(nèi)此功能目前沒有用
方式1:Android studio創(chuàng)建可下載字體
Android studio 3.0及以上可下載糙臼,以下以Android studio 3.1.3介紹
1.選擇more Fonts
2.選擇創(chuàng)建可下載字體
3.點(diǎn)擊ok庐镐,則會(huì)在font目錄下創(chuàng)建對(duì)應(yīng)的字體xml配置文件,內(nèi)容如下:
創(chuàng)建證書文件font_certs.xml
參數(shù)介紹:
fontProviderAuthority 字體提供app的權(quán)限
fontProviderPackage 字體提供app的包名变逃,用于獲取是哪個(gè)字體提供app
fontProviderQuery 字體提供app的字體名稱必逆,用于獲取是哪個(gè)字體
fontProviderCerts 字體提供app的證書
總結(jié):Android studio 生成的字體使用了兼容庫,已兼容低版本揽乱;證書的生成由Android studio 自動(dòng)生成名眉,不用管理
4.第3步點(diǎn)擊ok后,也會(huì)在AndroidManifest的application節(jié)點(diǎn)下生成如下內(nèi)容:
創(chuàng)建預(yù)加載字體文件preloaded_fonts.xml
介紹:以上是聲明使用預(yù)加載字體锤窑,如果沒有使用預(yù)加載字體璧针,則會(huì)在第一次設(shè)置可下載字體的時(shí)候嚷炉,會(huì)先下載字體然后設(shè)置渊啰,這樣會(huì)增加布局繪制時(shí)間,所以在AndroidManifest下聲明要預(yù)加載的字體申屹,則會(huì)在app啟動(dòng)時(shí)就加載即可解決這個(gè)問題绘证,如果下載出現(xiàn)超時(shí)或無網(wǎng)等失敗則會(huì)使用默認(rèn)字體
方式2:代碼創(chuàng)建可下載字體
以下使用了兼容庫,參數(shù)和上面一致
// 創(chuàng)建請求
FontRequest request = new FontRequest(
"com.google.android.gms.fonts",
"com.google.android.gms",
query,
R.array.com_google_android_gms_fonts_certs);
// 請求回調(diào)
FontsContractCompat.FontRequestCallback callback = new FontsContractCompat.FontRequestCallback() {
@Override
public void onTypefaceRetrieved(Typeface typeface) {
// 成功
mDownloadableFontTextView.setTypeface(typeface);
}
@Override
public void onTypefaceRequestFailed(int reason) {
}
};
// 請求
FontsContractCompat.requestFont(MainActivity.this, request, callback, getHandlerThreadHandler());
Demo github地址: Downloadable Fonts sample app
總結(jié):
適用于:不適用國內(nèi)
個(gè)人博客地址: devbolg