序
在 Android 下使用自定義字體已經(jīng)是一個比較常見的需求了亭罪,最近也做了個比較深入的研究瘦馍。
那么按照慣例我又要出個一篇有關(guān) Android 修改字體相關(guān)的文章,但是寫下來發(fā)現(xiàn)內(nèi)容還挺多的应役,所以我決定將它們拆分一下情组,分幾篇來詳細的講解燥筷。主要會是一些常用的替換字體的方案,最后還會介紹一些全局替換的方案院崇,當然也會包含最新的 『Fonts in XML』的方案肆氓。
期待你持續(xù)關(guān)注。
本篇是本系列的第六篇底瓣,之前已經(jīng)發(fā)布的文章谢揪,有興趣可以先看看。
- Android 字體修改概述|開篇
- 修改字體需要了解 Typeface 的所有細節(jié)
- 簡單粗暴的方式捐凭,修改字體
- 利用反射拨扶,修改全局字體
- 利用 AppCompatDelegate ,全局替換全局字體
一茁肠、前言
上一篇講解了通過替換 AppCompatDelegate 來達到替換控件的目的患民,從而替換成我們需要的可設(shè)置自定義字體的控件,來達到替換字體的目的官套。
現(xiàn)在大多數(shù)人應(yīng)該看出來了酒奶,到最后實現(xiàn)的目標就是如何快速、低入侵的替換全局控件奶赔,然后對這些控件進行重寫惋嚎,就可以達到我們很多的目的。換字體只是這其中的一種應(yīng)用站刑,還有其它的另伍,例如:換膚、無痕埋點等等绞旅,都是有可借鑒的地方的摆尝。
本文再介紹一種方式,通過 LayoutInflaterCompat.setFactory()
替換掉 LayoutInflaterFactory 或者 LayoutInflater.Factory2因悲,來達到我們替換控件的目的堕汞,從而實現(xiàn)全局字體的替換。
接下來開始介紹所有的技術(shù)細節(jié)晃琳。
二讯检、setFactory()
2.1 setFactory() 的技術(shù)原理
對大家而言,LayoutInflater 應(yīng)該是不陌生的卫旱,所有需要動態(tài)加載 layout-xml 中的 View 的地方都需要用到它的 inflater()
方法人灼,例如:ListView、RecyclerView顾翼。
而本文需要用到的是它另外兩個 Api 方法投放,setFactory()
和 setFactory2()
。它們的方法簽名如下适贸。
這兩個方法分別接收 Factory 和 Factory2 灸芳,它們兩個都是 Interface涝桅。并且這兩個方法的功能也是類似的。只是 setFactory2()
是在 Api Level 11 之后引入的耗绿,使用那個取決于項目的 minSdkVersion苹支。
不過一般而言,我們也不需要直接使用它误阻。我們需要只用 Support.v4 包中,為我們提供的 LayoutInflaterCompat 這個兼容類來做處理晴埂。和所有的兼容類一樣究反,它其中會有一個 IMPL 的變量,會根據(jù)不同的 Api Level 初始化不同的實例儒洛。
可以看到精耐,這里只對 Api Level 21 作為一個分界,去處理邏輯琅锻,其中會有不同的實現(xiàn)卦停,這里有興趣可以一探究竟,有時間會單獨出一篇文章來講解恼蓬,這里就不再深入了惊完。
這里,我們需要用到 LayoutInflaterCompat.setFactory()
方法处硬,它實際上已經(jīng)被標記為 @Deprecated
了小槐,一般推薦我們使用 LayoutInflaterCompat.setFactory2()
,但是它們的功能是一致的荷辕,這里就不糾結(jié)這些細節(jié)了凿跳。
可以看到,setFactory()
接收一個 LayoutInflaterFactory 的對象疮方,它實際上是一個接口控嗜,需要我們實現(xiàn)其中的 onCreateView()
方法。
我們這里主要的功能骡显,就在于實現(xiàn) onCreateView()
方法疆栏,將我們需要的控件在這個方法中替換掉。
2.2 舉個例子
對著源碼說太干了蟆盐。下面我舉個實際的例子承边,相信就可以說明問題了。
首先我新建一個 Activity石挂,在 super.onCreate()
之前博助,通過 LayoutInflaterCompat 重新設(shè)置 Factory,在關(guān)鍵地方打印好 Log痹愚。
再聲明一個布局富岳,讓它去顯示 layout-XML 布局蛔糯,層級很簡單,就是一個 LinearLayout 中間包含了一個 TextView窖式。
然后蚁飒,我們運行起來看看輸出的 Log ,這里撇開了 DecorView 等這些布局的打印萝喘,只看關(guān)鍵部分淮逻。
從 Log 輸出可以看出,實際上阁簸,你所有布局的控件爬早,都會經(jīng)過 LayoutInflaterFactory.onCreateView()
方法走一遍,去實現(xiàn)初始化的過程启妹,在其中可以有效的分辨出是什么控件筛严,以及它有什么屬性。
并且 onCreateView()
方法的返回值饶米,就是一個 View桨啃,如果要替換該 View,可以在此處將其初始化后返回回去即可檬输。
三照瘾、利用 LayoutInflater 替換字體
既然原理都清楚了,那么我們接下來就開始實際操作一下褪猛,如何通過替換 LayoutInflaterFactory 來達到替換控件网杆,從而達到替換字體的目的。
首先伊滋,定義一個 Activity 為基類碳却,其中在 super..onCreate()
方法之前,調(diào)用 LayoutInflaterCompat.setFactory()
笑旺,然后將它的替換為 我們自己定義的 CustomFontCompatDelegate 類昼浦。
CustomFontCompatDelegate 的實現(xiàn),也非常的簡單筒主,只需要在它的 onCreateView()
方法中关噪,替換掉 TextView 就可以。
其實乌妙,所有替換字體的邏輯使兔,都在 FontTextView 中,接下來我們再看看 FontTextView 的邏輯藤韵。
可以看到虐沥,在 FontTextView 中,直接完整的將字體替換成我們在 assets 目錄下存放的 custom_font.ttf
字體文件。
到這里就完成了基本的功能欲险,我們接下來看看如何使用它镐依。
只需要使用一個 Activity ,繼承我們剛才實現(xiàn)的 CustomFontActivity天试,然后寫一個簡單的布局槐壳,其中有三個 TextView。
最后,我們再來看看運行后的效果。
四、小結(jié)
到這里基本上就介紹清楚如何通過 LayoutInflaterCompat.setFactory()
去替換 Factory 這個接口,達到我們替換控件的目的贸铜,從而完美的替換全局的字體。
但是實際開發(fā)過程中,依然需要考慮所有可以顯示文字的控件乘盼,例如:TextView、EditText沃于、Button 等等涩咖,這些都是我們需要重寫的控件。
點贊或者分享吧~