在 Android 下使用自定義字體已是一個比較常見的需求了,最近也作了個比較深刻的研究。java
那麼按照慣例我又要出個一篇有關 Android 修改字體相關的文章,可是寫下來發現內容還挺多的,因此我決定將它們拆分一下,分幾篇來詳細的講解。主要會是一些經常使用的替換字體的方案,最後還會介紹一些全局替換的方案,固然也會包含最新的 『Fonts in XML』的方案。佈局
期待你持續關注。字體
本篇是本系列的第六篇,以前已經發布的文章,有興趣能夠先看看。3d
上一篇講解了經過替換 AppCompatDelegate 來達到替換控件的目的,從而替換成咱們須要的可設置自定義字體的控件,來達到替換字體的目的。code
如今大多數人應該看出來了,到最後實現的目標就是如何快速、低入侵的替換全局控件,而後對這些控件進行重寫,就能夠達到咱們不少的目的。換字體只是這其中的一種應用,還有其它的,例如:換膚、無痕埋點等等,都是有可借鑑的地方的。cdn
本文再介紹一種方式,經過 LayoutInflaterCompat.setFactory()
替換掉 LayoutInflaterFactory 或者 LayoutInflater.Factory2,來達到咱們替換控件的目的,從而實現全局字體的替換。xml
接下來開始介紹全部的技術細節。對象
對你們而言,LayoutInflater 應該是不陌生的,全部須要動態加載 layout-xml 中的 View 的地方都須要用到它的 inflater()
方法,例如:ListView、RecyclerView。blog
而本文須要用到的是它另外兩個 Api 方法,setFactory()
和 setFactory2()
。它們的方法簽名以下。繼承
這兩個方法分別接收 Factory 和 Factory2 ,它們兩個都是 Interface。而且這兩個方法的功能也是相似的。只是 setFactory2()
是在 Api Level 11 以後引入的,使用那個取決於項目的 minSdkVersion。
不過通常而言,咱們也不須要直接使用它。咱們須要只用 Support.v4 包中,爲咱們提供的 LayoutInflaterCompat 這個兼容類來作處理。和全部的兼容類同樣,它其中會有一個 IMPL 的變量,會根據不一樣的 Api Level 初始化不一樣的實例。
能夠看到,這裏只對 Api Level 21 做爲一個分界,去處理邏輯,其中會有不一樣的實現,這裏有興趣能夠一探究竟,有時間會單獨出一篇文章來說解,這裏就再也不深刻了。
這裏,咱們須要用到 LayoutInflaterCompat.setFactory()
方法,它實際上已經被標記爲 @Deprecated
了,通常推薦咱們使用 LayoutInflaterCompat.setFactory2()
,可是它們的功能是一致的,這裏就不糾結這些細節了。
能夠看到,setFactory()
接收一個 LayoutInflaterFactory 的對象,它其實是一個接口,須要咱們實現其中的 onCreateView()
方法。
咱們這裏主要的功能,就在於實現 onCreateView()
方法,將咱們須要的控件在這個方法中替換掉。
對着源碼說太乾了。下面我舉個實際的例子,相信就能夠說明問題了。
首先我新建一個 Activity,在 super.onCreate()
以前,經過 LayoutInflaterCompat 從新設置 Factory,在關鍵地方打印好 Log。
再聲明一個佈局,讓它去顯示 layout-XML 佈局,層級很簡單,就是一個 LinearLayout 中間包含了一個 TextView。
而後,咱們運行起來看看輸出的 Log ,這裏撇開了 DecorView 等這些佈局的打印,只看關鍵部分。
從 Log 輸出能夠看出,實際上,你全部佈局的控件,都會通過 LayoutInflaterFactory.onCreateView()
方法走一遍,去實現初始化的過程,在其中能夠有效的分辨出是什麼控件,以及它有什麼屬性。
而且 onCreateView()
方法的返回值,就是一個 View,若是要替換該 View,能夠在此處將其初始化後返回回去便可。
既然原理都清楚了,那麼咱們接下來就開始實際操做一下,如何經過替換 LayoutInflaterFactory 來達到替換控件,從而達到替換字體的目的。
首先,定義一個 Activity 爲基類,其中在 super..onCreate()
方法以前,調用 LayoutInflaterCompat.setFactory()
,而後將它的替換爲 咱們本身定義的 CustomFontCompatDelegate 類。
CustomFontCompatDelegate 的實現,也很是的簡單,只須要在它的 onCreateView()
方法中,替換掉 TextView 就能夠。
其實,全部替換字體的邏輯,都在 FontTextView 中,接下來咱們再看看 FontTextView 的邏輯。
能夠看到,在 FontTextView 中,直接完整的將字體替換成咱們在 assets 目錄下存放的 custom_font.ttf
字體文件。
到這裏就完成了基本的功能,咱們接下來看看如何使用它。
只須要使用一個 Activity ,繼承咱們剛纔實現的 CustomFontActivity,而後寫一個簡單的佈局,其中有三個 TextView。
最後,咱們再來看看運行後的效果。
到這裏基本上就介紹清楚如何經過 LayoutInflaterCompat.setFactory()
去替換 Factory 這個接口,達到咱們替換控件的目的,從而完美的替換全局的字體。
可是實際開發過程當中,依然須要考慮全部能夠顯示文字的控件,例如:TextView、EditText、Button 等等,這些都是咱們須要重寫的控件。
點贊或者分享吧~