全局替换字体,开源库更方便!!!
序
在 Android 下使用自定義字體已經(jīng)是一個(gè)比較常見的需求了,最近也做了個(gè)比較深入的研究。
那么按照慣例我又要出個(gè)一篇有關(guān) Android 修改字體相關(guān)的文章,但是寫下來(lái)發(fā)現(xiàn)內(nèi)容還挺多的,所以我決定將它們拆分一下,分幾篇來(lái)詳細(xì)的講解。主要會(huì)是一些常用的替換字體的方案,最后還會(huì)介紹一些全局替換的方案,當(dāng)然也會(huì)包含最新的 『Fonts in XML』的方案。
期待你持續(xù)關(guān)注。
本篇是本系列的第九篇,之前已經(jīng)發(fā)布的文章,有興趣可以先看看。
- Android 字體修改概述|開篇
- 修改字體需要了解 Typeface 的所有細(xì)節(jié)
- 簡(jiǎn)單粗暴的方式,修改字體
- 利用反射,修改全局字體
- 利用 AppCompatDelegate ,全局替換全局字體
- 通過(guò)修改 LayoutInflater,全局替換字體!
- 自定義屬性,支持多個(gè)字體文件!
- Android 可下載字體,Font in xml!
一、前言
之前已經(jīng)介紹了很多種,快速、低入侵的替換全局字體的方式。但是大多數(shù)情況下,我們需要實(shí)現(xiàn)的功能,一定已經(jīng)有現(xiàn)成的實(shí)現(xiàn)方案。
本文就介紹一個(gè) Github 上,比較火的全局替換字體的開源庫(kù),差不多閱讀文檔加集成,一個(gè)小時(shí)全局替換字體不是夢(mèng)。
這個(gè)開源替換字體庫(kù)就是 Calligraphy:
https://github.com/chrisjenx/...
二、如何使用Calligraphy
既然是要接入開源庫(kù)來(lái)全局替換字體,先來(lái)看看它可以實(shí)現(xiàn)的效果。
接下來(lái),我們開始一步步集成它。
2.1 添加 Gradle 依賴
Calligraphy 支持 Gradle 和 jar 的接入方式,這里使用 Gradle 來(lái)接入。
2.2 添加字體文檔到項(xiàng)目?jī)?nèi)
Calligraphy 支持的文件,可以放在 assets/ 目錄下,當(dāng)然,我們可以再在其中建立一個(gè)文件夾來(lái)專門的存放字體文件。
2.3 初始化 Calligraphy
Calligraphy 使用 CalligraphyConfig 類,來(lái)進(jìn)行初始化。它需要在 App 的入口,Application.onCreate() 中調(diào)用。
初始化主要是為了指定一些默認(rèn)的配置,例如:默認(rèn)字體、默認(rèn)屬性值。
2.4 替換 Context
Calligraphy 對(duì) Activity 的 Context,進(jìn)行了一次包裝,需要使用它包裝的 Context,才可以達(dá)到替換字體的效果。所以還需要重寫 BaseActivity 中的 attachBaseContext() 方法,將其替換成 Calligraphy 為我們提供的 Context 的包裝類 CalligraphyContextWrapper。
2.5 使用 Calligraphy
到這里,就完成了 Calligraphy 的配置了,我們只需要在 TextView 中,通過(guò)屬性去使用它就好了,它配置的是我們字體文件,在 assets 目錄下的路徑。
2.6 查缺補(bǔ)漏
Calligraphy 使用起來(lái)還是很方便的,并且也支持更多的配置方式,例如: Style、Theme 都可以。
具體的使用細(xì)節(jié),大家還是閱讀文檔了解更方便。
三、Calligraphy的原理
我們使用一個(gè)開源庫(kù),當(dāng)然要理解它的原理才能放心使用在商業(yè)項(xiàng)目上,接下來(lái),我們就來(lái)分析一下 Calligraphy 的實(shí)現(xiàn)原理,看看和之前介紹的方式,有沒(méi)有什么區(qū)別。
先來(lái)看看 Calligraphy 的整體結(jié)構(gòu)。
可以看到,它一共需要的類非常的少,算是一個(gè)比較精簡(jiǎn)的庫(kù)了,并且它并沒(méi)有重寫 TextView ,所以應(yīng)該是通過(guò)其它的方式來(lái)做到字體的替換的。
我們先來(lái)看看在 Application 需要調(diào)用的配置類, CalligraphyConfig 的源碼。
CalligraphyConfig 使用 Builder 的模式去初始化自己,可以看到這里只是設(shè)置了一些配置項(xiàng),并沒(méi)有實(shí)際的業(yè)務(wù)邏輯。
CalligraphyConfig 初始化之后,就以靜態(tài)變量存儲(chǔ)起來(lái),供其它地方使用,是一種單例的模式,但是并沒(méi)有考慮線程安全的問(wèn)題。
既然 CalligraphyConfig 沒(méi)有實(shí)際的邏輯,那么接下去應(yīng)該如何追蹤重要的代碼呢?
仔細(xì)觀察之前配置項(xiàng)里,需要重寫 Activity.attachBaseContext() 方法,這里會(huì)傳遞它重寫的一個(gè) Context 的包裝類 CalligraphyContextWrapper,所以接下來(lái)我們?cè)倏纯?CalligraphyContextWrapper 的源碼邏輯。
讀了 CalligraphyContextWrapper 源碼之后,你會(huì)發(fā)現(xiàn)它最重要的就是重寫了 getSystemService() 方法,當(dāng)它是 LAYOUT_INFLATER_SERVICE 的時(shí)候,將自己的 CalligraphyLayoutInflater 類,返回回去。
那么,這里的 LAYOUT_INFLATER_SERVICE 到底是什么呢?
我想大家應(yīng)該對(duì) LayoutInflater 不陌生,從 layout-xml 加載 View 的時(shí)候,都需要用到它,相信下面這段代碼,應(yīng)該大家都不陌生。
再仔細(xì)看看 LayoutInflater.from() 方法的源碼。
可以看到,這里獲得 LayoutInflater 對(duì)象的時(shí)候,用到的就是 LAYOUT_INFLATER_SERVICE。
所以 CalligraphyContextWrapper.getSystemService() 方法被重寫的目的,就是為了替換掉 LayoutInflater 對(duì)象,所以可以猜想,設(shè)置自定義字體的地方,就在自定義的 LayoutInflater 中。
繼續(xù)查看 CalligraphyLayoutInflater 的源碼,最終修改字體的邏輯,是在 CalligraphyContextWrappe 的 onViewCreatedInternal() 方法里面。
它會(huì)取出我們自定義屬性上設(shè)置的值,然后設(shè)置到初始化好的 TextView 上去。
四、Calligraphy 小結(jié)
到此就完成了 Calligraphy 的主要邏輯追蹤,幾個(gè)核心技術(shù)點(diǎn):
當(dāng)然,實(shí)際上,開源庫(kù)之所以可以流傳的比較廣,它還做了更多的細(xì)節(jié)處理,但是我們一般分析開源庫(kù),只需要關(guān)心主線邏輯就可以了。
整體來(lái)說(shuō) Calligraphy 沒(méi)有什么大毛病,可以放心使用,當(dāng)然如果你用了一些同樣依賴此原理的第三方庫(kù),可能會(huì)有沖突,這個(gè)就只能具體問(wèn)題具體分析了。
今天在承香墨影公眾號(hào)的后臺(tái),回復(fù)『成長(zhǎng)』。我會(huì)送你一些我整理的學(xué)習(xí)資料,包含:Android反編譯、算法。Web項(xiàng)目源碼。
推薦閱讀:
- Glide 這樣用,更省內(nèi)存!!!
- 跳槽前,不思考這些等于白跳!!!
- 哪些年熬過(guò)的夜,終將會(huì)"回報(bào)"你的
- 當(dāng)你只有一個(gè)設(shè)備的時(shí)候,如何做好屏幕適配
- Android 源碼,在線閱讀更方便!!!
點(diǎn)贊或者分享吧~
總結(jié)
以上是生活随笔為你收集整理的全局替换字体,开源库更方便!!!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python-练习7
- 下一篇: 爆牙齿的世界杯日记(小组首轮)