通过修改 LayoutInflater,全局替换字体!!!
序
在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究。
那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我决定将它们拆分一下,分几篇来详细的讲解。主要会是一些常用的替换字体的方案,最后还会介绍一些全局替换的方案,当然也会包含最新的 『Fonts in XML』的方案。
期待你持续关注。
本篇是本系列的第六篇,之前已经发布的文章,有兴趣可以先看看。
一、前言
上一篇讲解了通过替换 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 等等,这些都是我们需要重写的控件。
点赞或者分享吧~
通过修改 LayoutInflater,全局替换字体!!!的更多相关文章
- iOS运用runtime全局修改UILabel的默认字体
iOS运用runtime全局修改UILabel的默认字体 一.需求背景介绍 在项目比较成熟的基础上,遇到了这样一个需求,应用中需要引入新的字体,需要更换所有Label的默认字体,但是同时,对于一些特殊 ...
- js replace 全局替换 以表单的方式提交参数 判断是否为ie浏览器 将jquery.qqFace.js表情转换成微信的字符码 手机端省市区联动 新字体引用本地运行可以获得,放到服务器上报404 C#提取html中的汉字 MVC几种找不到资源的解决方式 使用Windows服务定时去执行一个方法的三种方式
js replace 全局替换 js 的replace 默认替换只替换第一个匹配的字符,如果字符串有超过两个以上的对应字符就无法进行替换,这时候就要进行一点操作,进行全部替换. <scrip ...
- vim的全局替换
本文出自 http://blog.csdn.net/shuangde800 本文是在学习<使用vi编辑器, Lamb & Robbins编著>时在所记的笔记. 本文内容: 基本 ...
- vim的全局替换[zz]&把字符替换成回车
本文出自 http://blog.csdn.net/shuangde800 本文是在学习<使用vi编辑器, Lamb & Robbins编著>时在所记的笔记. 本文内容 ...
- 修改WordPress标签云字体大小颜色及标签显示数量
WordPress 自带的标签云是一个很实用的小工具.站长可以通过标签对具有相同关健词的文章进行检索分类,利于访客查找相关文章.WordPress 默认标签云的字体最小为8pt,最大为22pt,标签显 ...
- vi全局替换
http://blog.csdn.net/vindak/article/details/7830547 vi全局替换命令
- vim 全局替换命令
语法 :[addr]s/源字符串/目的字符串/[option] :%s/源字符串/目的字符串/c 全局替换命令为: :%s/源字符串/目的字符串/g [add ...
- vim全局替换
:1,$ s/cmss_//g 1,$代表第一行到最后一行 s代表替换 cmss_为要替换的内容 替换为空格,所以直接// g代表全局替换
- 修改UITextfield的Placeholder字体的颜色
- (void)viewDidLoad { [super viewDidLoad]; self.title=@"修改UITextField的placeholder字体颜色"; UI ...
随机推荐
- 字符编码知识简介和iconv函数的简单使用
字符编码知识简介和iconv函数的简单使用 字符编码知识简介 我们知道,在计算机的世界其实只有0和1.期初计算机主要用于科学计算,而我们知道一个数,除了用我们常用对10进制表示,也可以用2进制表示,所 ...
- docker学习之--日常命令
.查看镜像 sudo docker images sudo pull docker.io #下载镜像 sudo push docker.io #上传镜像 sudo docker save -o cen ...
- [js高手之路]Vue2.0基于vue-cli+webpack同级组件之间的通信教程
我们接着上文继续,本文我们讲解兄弟组件的通信,项目结构还是跟上文一样. 在src/assets目录下建立文件EventHandler.js,该文件的作用在于给同级组件之间传递事件 EventHandl ...
- JMeter打开脚本失败 如何解决?
最近有碰到JMeter打开之前的脚本,报错了,见下图: 后来发现这是因为之前保存脚本的 jmeter 和这次打开脚本的 jmeter 版本不一致(图一)或者版本一致而插件没有保持同步(图二)的原因: ...
- oop作业二—circle
oop作业-circle 题目描述 编写一个程序,要求根据给定的圆的半径求圆的面积,并将求得的结果打印出来. 要求: 输入输出采用cin和cout. 建立一个工程,将程序写成两个.cpp和一个.h的形 ...
- 【集美大学1411_助教博客】团队作业4——第一次项目冲刺(Alpha版本) 成绩
写在前面的话 第一次alpha冲刺,大家完成得都很好,从博客中体现出来的是所有团队都完成了预期的目标. 一个团队从最初建立,到磨合,到做出一个能被接受的产品,真是一件不容易的事情.就好像TheNexu ...
- 201521123001《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 201521123042 Java第一周学习总结
1. 201521123042 <Java程序设计>第一周学习总结 a.用notepad++和eclipse编写Java程序 b.安装Java Q1.为什么java程序可以跨平台运行?执行 ...
- 201521123104 《Java程序设计》 第12周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...
- iOS启动图-从网络获取的gif图,在本地一直是没有动画,还模糊的
背景介绍:APP启动页,常有静态图加链接,gif加链接,短视频等几种形式.我们APP前期只有静态图这一种,功能已经实现.之后,有了添加gif的需求,按理说,只要添加一个类型判断,按照数据类型,通过不同 ...