序
在 Android 下使用自定義字型已經是一個比較常見的需求了,最近也做了個比較深入的研究。
那麼按照慣例我又要出個一篇有關 Android 修改字型相關的文章,但是寫下來發現内容還挺多的,是以我決定将它們拆分一下,分幾篇來詳細的講解。主要會是一些常用的替換字型的方案,最後還會介紹一些全局替換的方案,當然也會包含最新的 『Fonts in XML』的方案。
期待你持續關注。
本篇是本系列的第六篇,之前已經釋出的文章,有興趣可以先看看。
- Android 字型修改概述|開篇
- 修改字型需要了解 Typeface 的所有細節
- 簡單粗暴的方式,修改字型
- 利用反射,修改全局字型
- 利用 AppCompatDelegate ,全局替換全局字型
一、前言
上一篇講解了通過替換 AppCompatDelegate 來達到替換控件的目的,進而替換成我們需要的可設定自定義字型的控件,來達到替換字型的目的。
現在大多數人應該看出來了,到最後實作的目标就是如何快速、低入侵的替換全局控件,然後對這些控件進行重寫,就可以達到我們很多的目的。換字型隻是這其中的一種應用,還有其它的,例如:換膚、無痕埋點等等,都是有可借鑒的地方的。
本文再介紹一種方式,通過
LayoutInflaterCompat.setFactory()
替換掉 LayoutInflaterFactory 或者 LayoutInflater.Factory2,來達到我們替換控件的目的,進而實作全局字型的替換。
接下來開始介紹所有的技術細節。
二、setFactory()
2.1 setFactory() 的技術原理
對大家而言,LayoutInflater 應該是不陌生的,所有需要動态加載 layout-xml 中的 View 的地方都需要用到它的
inflater()
方法,例如:ListView、RecyclerView。
而本文需要用到的是它另外兩個 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()
方法,将我們需要的控件在這個方法中替換掉。
2.2 舉個例子
對着源碼說太幹了。下面我舉個實際的例子,相信就可以說明問題了。
首先我建立一個 Activity,在
super.onCreate()
之前,通過 LayoutInflaterCompat 重新設定 Factory,在關鍵地方列印好 Log。
再聲明一個布局,讓它去顯示 layout-XML 布局,層級很簡單,就是一個 LinearLayout 中間包含了一個 TextView。
然後,我們運作起來看看輸出的 Log ,這裡撇開了 DecorView 等這些布局的列印,隻看關鍵部分。
從 Log 輸出可以看出,實際上,你所有布局的控件,都會經過
LayoutInflaterFactory.onCreateView()
方法走一遍,去實作初始化的過程,在其中可以有效的分辨出是什麼控件,以及它有什麼屬性。
并且
onCreateView()
方法的傳回值,就是一個 View,如果要替換該 View,可以在此處将其初始化後傳回回去即可。
三、利用 LayoutInflater 替換字型
既然原理都清楚了,那麼我們接下來就開始實際操作一下,如何通過替換 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 等等,這些都是我們需要重寫的控件。
點贊或者分享吧~
作者:承香墨影
出處:http://plokmju.cnblogs.com/
如非授權,禁止轉載!