Android中以粗暴的方式替換全局字體
序
在 Android 下使用自定義字體已經(jīng)是一個比較常見的需求了,最近也做了個比較深入的研究。
那么按照慣例我又要出個一篇有關 Android 修改字體相關的文章,但是寫下來發(fā)現(xiàn)內(nèi)容還挺多的,所以我決定將它們拆分一下,分幾篇來詳細的講解(可能是五篇)。主要會是一些常用的替換字體的方案,***還會介紹一些全局替換的方案,當然也會包含***的 『Fonts in XML』的方案。
期待你持續(xù)關注。
本篇是本系列的第二篇,之前已經(jīng)發(fā)布的文章,有興趣可以先看看。
一、前言
前面已經(jīng)分析了修改字體的所有細節(jié),以及與修改字體相關的 Typeface 類,接下來就開始討論如何修改全局字體。
本篇會先介紹兩種比較粗暴的方式來修改全局的字體。
二、自定義控件
在開始一個新的項目的時候,一般習慣好點的都會定義一個 BaseActivity 和 BaseFragment 來作為頁面的基類,這樣可以方便我們在之后的時候,對所有頁面增加一些統(tǒng)一的邏輯。
不過應該不會有人提前想到要給所有的控件,提前定義一個自定義的控件實現(xiàn)。
但是如果在開發(fā)的初期,就已經(jīng)考慮到字體需要修改的情況的話,是可以重寫一些字體顯示相關的控件。來達到全局替換字體的作用的。
Android 中,最常用的用來顯示字體的控件,就是 TextView,這里就重寫一個 TextView 來達到替換字體的效果。
在 TextView 中,可以通過 setTypeface() 方法,為 TextView 設置一個字體,setTypeface() 方法有兩個重載方法,無非就是多傳遞了一個需要設置的 textStyle,用來標記粗體和斜體。
其實最終都是調(diào)用一個參數(shù)的 setTypeface(,它才是設置的關鍵。
可以看到,設置字體實際上是操作的 mTextPaint,mTextPaint 是 TextPaint 類的對象,直接繼承自 Paint,就是一個用來繪制文字的畫筆。
那么,我們就可以直接自定義一個 TextView ,在構造函數(shù)中,通過 setTypeface() 方法,來修改 TextView 的字體。
主要代碼如下:
注意,這里還需要考慮在布局中,為我們設定的 FontTextView 設置的 textStyle 屬性,可能是粗體或者斜體。
通常設計師為了考慮 App 的 UI 統(tǒng)一性和協(xié)調(diào)性,一般都會選用一個字體,所以將需要替換的字體封裝在 FontTextView 中,也沒有什么大的問題。
那么來驗證看看實現(xiàn)出來的效果,這里專門選擇了一個比較特殊的字體。在布局 xml 文件中,添加三個 FontTextView。
再來看看運行的效果。
這里也考慮了在布局中設置的 textStyle,并且一個已經(jīng)比較傾斜的字體,使用 italic 標記之后,更傾斜了。
這個方法,如果在開發(fā)初期,還可以接受,無非就是寫布局的時候,需要注意使用自定義的控件,同時還除了 TextView ,還需要重寫 Button、EditText 等一系列需要顯示文字的控件,說到底還是有點麻煩的。
而且如果是在一個已經(jīng)成熟的項目上再使用這種方案,改動起來還是很費勁的,基本上就是一通文本替換,改動會比較大一些。
三、遍歷 ViewTree
在 Android 中,用于顯示文本的控件,都是直接或者間接集成自 TextView 的,那么我們只需要找一個合適的時機,遍歷布局的 ViewTree,將其中所有 TextView 的子類都獲取出來,然后批量修改它們的字體,同樣也可以達到全局替換的效果。
在這個 replaceCustomFont() 的方法里,回去判斷是否繼承自 TextView,如果是就替換字體。如果不是,再判斷是否是一個 ViewGroup,如果是的話,從其內(nèi)取出所有的子 View,再遞歸調(diào)用 replaceCustomFont() 方法。
通常,為了在合適的時機修改字體,我們可以將這個方法加在 Activity.onCreate() 方法,或者 Fragment.onCreateView() 方法的后面,修改的地方,相對少一些,不過還需要考慮 ListView、RecyclverView 這種動態(tài)生成 View 的邏輯,也需要注意不能遺漏。
舉個例子,寫一個布局,在 Activity.onCreate() 方法中,調(diào)用 replaceCustomFont() 方法。
***展現(xiàn)的效果如下。
使用這種方式,優(yōu)點是,不需要修改 XML 布局,不需要重寫多個控件。只需要在 Inflater View 的之后,調(diào)用一下 replaceCustomFont() 方法即可。
缺點也非常的明顯,每個頁面都需要修改,有動態(tài)加載 View 的地方可能會被遺漏,改動相比較之前的方案,稍微少一點。并且違背了組件的設計原則,實現(xiàn)方式也略顯粗暴。同時它每次都會遞歸遍歷 ViewTree,性能上多少都會有點影響。
四、小結
本文介紹的幾個辦法,在實際開發(fā)中,可能也用不上。不過不影響我們了解這樣的方法。
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉(zhuǎn)載請通過微信公眾號聯(lián)系作者獲取授權】