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