Android中,粗暴的方式,修改字体
序
在 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,性能上多少都会有点影响。
四、小结
本文介绍的几个办法,在实际开发中,可能也用不上。不过不影响我们了解这样的方法。
下期预告
到现在为止,介绍的替换字体的方案,其实并不够优雅。从下期开始,就会开始介绍一些更优雅的方式,在现有项目上,全局的替换字体的一些方案。期待你的持续关注。