在 Android 下使用自定义字体已是一个比较常见的需求了,最近也作了个比较深刻的研究。java
那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,可是写下来发现内容还挺多的,因此我决定将它们拆分一下,分几篇来详细的讲解。主要会是一些经常使用的替换字体的方案,最后还会介绍一些全局替换的方案,固然也会包含最新的 『Fonts in XML』的方案。布局
期待你持续关注。字体
本篇是本系列的第六篇,以前已经发布的文章,有兴趣能够先看看。3d
上一篇讲解了经过替换 AppCompatDelegate 来达到替换控件的目的,从而替换成咱们须要的可设置自定义字体的控件,来达到替换字体的目的。code
如今大多数人应该看出来了,到最后实现的目标就是如何快速、低入侵的替换全局控件,而后对这些控件进行重写,就能够达到咱们不少的目的。换字体只是这其中的一种应用,还有其它的,例如:换肤、无痕埋点等等,都是有可借鉴的地方的。cdn
本文再介绍一种方式,经过 LayoutInflaterCompat.setFactory()
替换掉 LayoutInflaterFactory 或者 LayoutInflater.Factory2,来达到咱们替换控件的目的,从而实现全局字体的替换。xml
接下来开始介绍全部的技术细节。对象
对你们而言,LayoutInflater 应该是不陌生的,全部须要动态加载 layout-xml 中的 View 的地方都须要用到它的 inflater()
方法,例如:ListView、RecyclerView。blog
而本文须要用到的是它另外两个 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()
方法,将咱们须要的控件在这个方法中替换掉。
对着源码说太干了。下面我举个实际的例子,相信就能够说明问题了。
首先我新建一个 Activity,在 super.onCreate()
以前,经过 LayoutInflaterCompat 从新设置 Factory,在关键地方打印好 Log。
再声明一个布局,让它去显示 layout-XML 布局,层级很简单,就是一个 LinearLayout 中间包含了一个 TextView。
而后,咱们运行起来看看输出的 Log ,这里撇开了 DecorView 等这些布局的打印,只看关键部分。
从 Log 输出能够看出,实际上,你全部布局的控件,都会通过 LayoutInflaterFactory.onCreateView()
方法走一遍,去实现初始化的过程,在其中能够有效的分辨出是什么控件,以及它有什么属性。
而且 onCreateView()
方法的返回值,就是一个 View,若是要替换该 View,能够在此处将其初始化后返回回去便可。
既然原理都清楚了,那么咱们接下来就开始实际操做一下,如何经过替换 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 等等,这些都是咱们须要重写的控件。
点赞或者分享吧~