粗暴的方式,替换全局字体

作者: 承香墨影 | 来源:发表于2017-09-28 18:40 被阅读85次

    在 Android 下使用自定义字体已经是一个比较常见的需求了,最近也做了个比较深入的研究。

    那么按照惯例我又要出个一篇有关 Android 修改字体相关的文章,但是写下来发现内容还挺多的,所以我决定将它们拆分一下,分几篇来详细的讲解(可能是五篇)。主要会是一些常用的替换字体的方案,最后还会介绍一些全局替换的方案,当然也会包含最新的 『Fonts in XML』的方案。

    期待你持续关注。

    本篇是本系列的第三篇,之前已经发布的文章,有兴趣可以先看看。

    一、前言

    前面已经分析了修改字体的所有细节,以及与修改字体相关的 Typeface 类,接下来就开始讨论如何修改全局字体。

    本篇会先介绍两种比较粗暴的方式来修改全局的字体。

    二、自定义字体相关的控件类

    在开始一个新的项目的时候,一般习惯好点的都会定义一个 BaseActivity 和 BaseFragment 来作为页面的基类,这样可以方便我们在之后的时候,对所有页面增加一些统一的逻辑。

    不过应该不会有人提前想到要给所有的控件,提前定义一个自定义的控件实现。

    但是如果在开发的初期,就已经考虑到字体需要修改的情况的话,是可以重写一些字体显示相关的控件。来达到全局替换字体的作用的。

    Android 中,最常用的用来显示字体的控件,就是 TextView,这里就重写一个 TextView 来达到替换字体的效果。

    在 TextView 中,可以通过 setTypeface() 方法,为 TextView 设置一个字体,setTypeface() 方法有两个重载方法,无非就是多传递了一个需要设置的 textStyle,用来标记粗体和斜体。

    /f-setTypeface.png

    其实最终都是调用一个参数的 setTypeface(,它才是设置的关键。

    /f-setTypeface1.png

    可以看到,设置字体实际上是操作的 mTextPaint,mTextPaint 是 TextPaint 类的对象,直接继承自 Paint,就是一个用来绘制文字的画笔。

    那么,我们就可以直接自定义一个 TextView ,在构造函数中,通过 setTypeface() 方法,来修改 TextView 的字体。

    主要代码如下:

    /f-fontTextView.png

    注意,这里还需要考虑在布局中,为我们设定的 FontTextView 设置的 textStyle 属性,可能是粗体或者斜体。

    通常设计师为了考虑 App 的 UI 统一性和协调性,一般都会选用一个字体,所以将需要替换的字体封装在 FontTextView 中,也没有什么大的问题。

    那么来验证看看实现出来的效果,这里专门选择了一个比较特殊的字体。在布局 xml 文件中,添加三个 FontTextView。

    /f-fontxml.png

    再来看看运行的效果。

    /f-fontimage.png

    这里也考虑了在布局中设置的 textStyle,并且一个已经比较倾斜的字体,使用 italic 标记之后,更倾斜了。

    这个方法,如果在开发初期,还可以接受,无非就是写布局的时候,需要注意使用自定义的控件,同时还除了 TextView ,还需要重写 Button、EditText 等一系列需要显示文字的控件,说到底还是有点麻烦的。

    而且如果是在一个已经成熟的项目上再使用这种方案,改动起来还是很费劲的,基本上就是一通文本替换,改动会比较大一些。

    三、遍历 ViewTree,替换字体

    在 Android 中,用于显示文本的控件,都是直接或者间接集成自 TextView 的,那么我们只需要找一个合适的时机,遍历布局的 ViewTree,将其中所有 TextView 的子类都获取出来,然后批量修改它们的字体,同样也可以达到全局替换的效果。

    /f-replaceroot.png

    在这个 replaceCustomFont() 的方法里,回去判断是否继承自 TextView,如果是就替换字体。如果不是,再判断是否是一个 ViewGroup,如果是的话,从其内取出所有的子 View,再递归调用 replaceCustomFont() 方法。

    通常,为了在合适的时机修改字体,我们可以将这个方法加在 Activity.onCreate() 方法,或者 Fragment.onCreateView() 方法的后面,修改的地方,相对少一些,不过还需要考虑 ListView、RecyclverView 这种动态生成 View 的逻辑,也需要注意不能遗漏。

    举个例子,写一个布局,在 Activity.onCreate() 方法中,调用 replaceCustomFont() 方法。

    /f-replascemain.png

    最后展现的效果如下。

    /f-fontimage.png

    使用这种方式,优点是,不需要修改 XML 布局,不需要重写多个控件。只需要在 Inflater View 的之后,调用一下 replaceCustomFont() 方法即可。

    缺点也非常的明显,每个页面都需要修改,有动态加载 View 的地方可能会被遗漏,改动相比较之前的方案,稍微少一点。并且违背了组件的设计原则,实现方式也略显粗暴。同时它每次都会递归遍历 ViewTree,性能上多少都会有点影响。

    四、小结

    本文介绍的几个办法,在实际开发中,可能也用不上。不过不影响我们了解这样的方法。

    下期预告

    到现在为止,介绍的替换字体的方案,其实并不够优雅。从下期开始,就会开始介绍一些更优雅的方式,在现有项目上,全局的替换字体的一些方案。期待你的持续关注。

    公众号二维码.jpg

    相关文章

      网友评论

      本文标题:粗暴的方式,替换全局字体

      本文链接:https://www.haomeiwen.com/subject/vtyvextx.html