Android 圖標自適應:用 TextView 來顯示圖片 & 生成自己的字體庫
Android 圖標自適應:用 TextView 來顯示圖片 & 生成自己的字體庫
今天我們來介紹一種用TextView代替并顯示圖片,以達到App優化及圖標自適應的效果。當然,我們先來看一下效果:

這些真的只是TextView文本
如果你看到上面這張圖片,第一反映你可能認為都是用ImageView去顯示的,那你就錯了,這些全都是用TextView實現的(當然更不可能是給 TextView 設置了背景圖)。
平時我們在開發中,圖片可謂是處處可見且必不可少的一部分,為了想盡辦法讓圖片達到適配的效果我們可能需要:
根據不同分辨率來提供多套圖,暫且不說這種方式是否麻煩,正常情況下我們切的三套或更多套圖有時候總在有些機型上的效果不盡人意。
可能這時候你想到了用 .9圖片 ,這時候且不說你們家 UI 妹子會不會單獨的為我們 Android 端提供 .9圖片 (姑且相信你們家UI會制作 .9 ),但是 .9圖片 是有一定的局限性的,它只能是圖片部分區域拉伸。
這篇文章 也并不是去介紹如何去做圖片的適配,而是介紹一種利用字體庫的方式,我們用 TextView 的形式去顯示圖片,而且我們還可以正常的使用 android:textSize 屬性來隨意設置圖片的大小!
其實這里通過 TextView 來顯示圖片的方式,我更愿意更準確的說成是通過 TextView 來顯示圖標 ,因為這里的圖片不是真正意義上的大圖而是相當于可以隨意拉伸的矢量圖。當然,如果你愿意你也可以用這種方式來顯示圖片。
啰嗦這么多,你的大刀是不是早就饑渴難耐了?其實這種方式很容易就能實現,只是通過給 TextView 設置一種字體,不要著急,馬上開始。
為TextView設置字體
大家都知道,在 android 中,我們如果要更換字體,除了要引入我們需要的字體庫外,還需要給我們的 TextView 去手動設置使用的字體,如何去設置呢?其實很簡單。
textView.setTypeface(Typeface tf);
盡管就這么一行代碼,但是,在我們項目中肯定會存在大量的TextView,難道我們要一個個的去動手設置嗎?想想這也是一件很頭疼的事,下面就介紹一種方便的方法,一行代碼解決字體設置的問題。
方法一:工具類 & 遞歸遍歷
在看代碼之前,先來看看思路,其實思路很簡單,我們提供一個根布局,寫一個方法去遞歸遍歷整個根布局,如果發現是textView,則設置字體。思路很簡單,相信代碼也很簡單,就是一個遞歸方法。
public class FontHelper {
public static final String DEF_FONT = "fonts/ocnyangfont.ttf";
public static final void injectFont(View rootView) {
injectFont(rootView, Typeface.createFromAsset(rootView.getContext().getAssets(),
DEF_FONT));
}
private static void injectFont(View rootView, Typeface typeface) {
if (rootView instanceof ViewGroup) {
ViewGroup viewGroup = (ViewGroup) rootView;
int childViewCount = viewGroup.getChildCount();
for (int i = 0; i < childViewCount; i++) {
injectFont(viewGroup.getChildAt(i), typeface);
}
} else if (rootView instanceof TextView) {
((TextView) rootView).setTypeface(typeface);
}
}
}</code></pre>
定義了一個工具類,這個類提供兩個靜態方法,但是核心都是
public static final void injectFont(View rootView, Typeface tf)
這個方法中,首先我們去判斷我們給的rootView是不是ViewGroup,如果是ViewGroup,則遍歷他的所有子view,然后遞歸去調用這個方法,直到全部完成,如果發現某個view是TextView,則我們調用setTypeface方法來設置字體。
ok,從這個工具類中我們還可以看到,我們的字體是放在assets/fonts目錄下的。
最后是在activity中使用字體庫,正式利用了上面的工具類,所以我們的代碼將會很簡單。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FontHelper.injectFont(findViewById(android.R.id.content));
}
僅僅一行代碼, FontHelper.injectFont(findViewById(android.R.id.content));
我們就完成了給所有TextView設置字體的工作。
方法二:LayoutInflate
現在對 LayoutInflateFactory 的用法還不太熟悉的,可以先去看一下鴻洋的這篇博文: 探究 LayoutInflate setFactory 。
我們編寫一個自定義的LayoutInflaterFactory:
public class IconFontLayoutFactory implements LayoutInflaterFactory {
private static Typeface sTypeface;
private AppCompatDelegate mAppCompatDelegate;
public IconFontLayoutFactory(Context context,
AppCompatDelegate appCompatDelegate) {
if (sTypeface == null) {
sTypeface = Typeface.createFromAsset(context.getAssets(),
"fonts/ocnyangfont.ttf");
}
mAppCompatDelegate = appCompatDelegate;
}
@Override
public View onCreateView(View parent, String name, Context context,
AttributeSet attrs) {
View view = mAppCompatDelegate.createView(parent, name, context, attrs);
if (view instanceof TextView) {
((TextView) view).setTypeface(sTypeface);
}
return view;
}
}</code></pre>
字體文件我們還是放在 assets/fonts 目錄下。
然后你可以在你的BaseActivity的onCreate中,調用如下代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
LayoutInflaterCompat.setFactory(getLayoutInflater(),
new IconFontLayoutFactory(this,getDelegate()));
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}</code></pre>
注意一定要在super.onCreate前調用即可。
該方式可以在TextView及其子類對象創建完成時,就可以為其調用setTypeFace,非常的高效。
而對于字體庫的加載,如果有需要,你甚至可以采用懶加載的方式,在SplashActivity中對其初始化。
這里提供是兩種全局設置的方式。
有時候我們只是需要給部分 TextView 設置,這時候大家可以選擇手動單獨給特定的 TextView 設置,也可以通過自定義 View 的方案來實現( 在構造方法中去設置 TypeFace ,我個人也比較提倡這種方式,使用上相對靈活,也很簡單這里就啰嗦了。
那上面這些只是如何設置字體的方法,可能你也早就知道了,字體是字體,也不是圖片呀,大兄弟莫慌,下面就給你如何介紹一種酷炫的字體庫和制作自己獨特的圖片字體庫的方法。
fontawesome 字體庫的使用
在開始使用之前,我們我們需要到
https://github.com/FortAwesome/Font-Awesome/
下載這個字體庫。下載下來以后,你會看到有很多目錄和文件,沒關系,我們只需要一個文件-fontawesome-webfont.ttf,這個文件位于/fonts/目錄下。將這個ttf文件copy到你項目的assets目錄下,按照慣例或者說是共識,我們可能是將它放到assets/fonts這個目錄下(注意,沒有這個目錄的話,創建它!)。
ok, 準備工作都做好了,那我們就開始使用它吧,看我的xml布局文件:
<LinearLayout
//...
>
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:textSize="58sp"
android:textColor="#ff995533"
android:layout_height="wrap_content"
android:text=""/>
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:textSize="118sp"
android:textColor="#ff9ff533"
android:layout_height="wrap_content"
android:text=""/>
//...
</LinearLayout></code></pre>
看到這個布局文件,我們看到和平時沒什么區別,給出了textSize或者textColor屬性,不用想這些肯定去控制了我們需要顯示的圖片的大小和顏色!
細心的你會發現這些 TextView 文本好奇怪。其實這些文本對應的就是相對于的圖片。可是,現在我們又遇到了一個問題,我們怎么知道哪寫文本代表了什么圖片呢?下面給出一個網址,通過這個網址,大家可以看到實體文本和他對應的圖片的一個對照表。
http://fortawesome.github.io/Font-Awesome/cheatsheet/
本文 源碼 內我們提供了一個 string.xml 文件的圖片字符對照表,可以直接在項目中使用。
你也可以在根據自己的需要在上面 string.xml 文件里 Ctrl + F 檢索出對應的編碼放到自己的字符串文件里或直接使用。
哦,對了,不知道大家有沒有發現,這里我們無意中解決了一個圖片大小的問題,因為我們可以任意改變一個文本的大小,所以,就不需要提供多套圖去適配不同的屏幕了。
這是你可能還是有疑問, Font-Awesome 庫 內提供的圖標雖然很全很美觀,但是不一定能滿足我們所有的需要啊!那現在就教大家如何制作屬于自己的字體庫。
制作屬于自己的圖片字體庫
在自己動手制作圖片字體庫之前,當然要先查找一些自己喜歡的漂亮的圖標了,下面開啟干貨福利模式。
圖標干貨
對于使用,最主要就是找到一些靠譜的素材站點了
https://icomoon.io/app/#/select
https://github.com/mikepenz/Android-Iconics
第一個站點是阿里提供的圖標庫,基本上可以搜索到需要的任何圖標,非常方便,也支持顏色和大小的設置,足夠滿足我們的需求:

阿里 iconfont 圖標庫
自定義圖標
無論上面這些網站提供的圖標是多么的全,可能都無法滿足貪心的你或者你們家追求完美(矯情)到極致的UI,那么如果App內的圖標部分是自己制作的,再混雜著網絡上已有的圖標能打包到一個字體庫么?
答案當然是肯定的,我們本來就是要制作屬于自己的字體庫嘛!比如你就可以依賴 iconfont.com 這個網站,自行上傳svg圖標,然后就可以自由選擇了。
按需生成自己的圖標字體庫
我們以 iconfont 庫為例,教大家 生成自己圖片字體庫的整個流程 (下面所有步驟,大家都無需注冊賬號,就可以直接使用)。
首先在 iconfont 網站上選擇自己要生成到字體庫的圖標,可以選擇網站字體庫中選擇,也可以在我的圖標庫中選擇自己上傳的圖標。把這些圖標添加到庫(即添加到購物車):

選擇喜歡的圖標

添加到購物車
當你想要生成的字體庫的圖標選擇完成后,在網站右上角點擊打開庫(購物車),在庫里可以看到自己選擇的所有圖標,確定后點擊下載代碼:

打開庫,下載代碼會得到一個壓縮包

解壓縮后,可以看到生成的庫
在解壓后的文件夾中,我們看到許多文件。其中以 .ttf 結尾的文件就是我們生成的自己的字體庫,而 3 個 .html 文件對應的是不同平臺使用時對應的編碼。而我們在 Android 開發中要使用的編碼是 demo_unicode.html 文件里對應的 &#xxxxx; 形式的編碼。
細心的你一定會發現,生成的字體庫里雖然包含了很多圖標,卻只有小小的幾 KB 的大小,更難能可貴的是無論設置多大的尺寸它依舊能夠保存一樣的清晰度,當然,你也可以把該方案看成apk瘦身的可選手段之一。
來自:http://www.jianshu.com/p/e95890e56bc2