在 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,性能上多少都会有点影响。

四、小结

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

下期预告

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

Android中,粗暴的方式,修改字体的更多相关文章

  1. Android Studio 3.1.2 修改字体(font)大小(size) 及老版本修改主题、字体、颜色 参照地址

    Android Studio 3.1.2  修改字体(font)大小(size) 步骤:File-Settings-Editor-Color Scheme-Color Scheme Font-Size ...

  2. 在Windows Server 2008 R2中使用web方式修改域用户账户密码

    在Windows的domain环境下,加域的客户端修改账户密码是一件很easy的事情:即使没有加域的客户端如果组织中,使用Exchange邮件系统,借助Exchange的owa也可以轻松修改账户密码. ...

  3. Android中的GreenDao框架修改数据库的存储路径

    目前android中比较热门的数据库框架有greenDAO.OrmLite.AndrORM,其中我比较喜欢用GreenDao,其运行效率最高,内存消耗最少,性能最佳.具体怎么使用GreenDao,网上 ...

  4. Android中的适配方式

    1,图片适配(在不同像素密度的手机上,加载不同文件夹下的图片) 一套图(800*480,将截取的图片放置在hdpi下,小图(变形不明显), 大图(根据适配的手机,做单独的截取,比如有两款手机适配(做两 ...

  5. android中两种方式打开网页

    一.你要打开一个网页你可以自己写一个webview,在自己的程序中就可以打开. wv = (WebView) findViewById(R.id.webView1); wv.getSettings() ...

  6. Android中 实现队列方式处理优先级信息

    需求:当界面在处理消息A时,突然接收到消息B,需要立马显示B的信息,然后再继续显示消息A,或者接收到消息C,再显示完消息A后再显示消息C: 原理很简单 在一个轮询中,查询消息列表中的元素,先处理优先级 ...

  7. Android中设置状态栏颜色和字体颜色

    1.在这里设置的状态栏背景为白色,字体为暗色 创建一个方法进行设置: protected void setStatusBar() { if (Build.VERSION.SDK_INT >= B ...

  8. Element中(Notification)通知组件字体修改(Vue项目中Element的Notification修改字体)

    这个问题纠结很久,一样的写的为啥有的页面就可以,有的就不行: 后来才发现: 先说一下怎么设置: 先定义customClass一个属性,用来写class属性值: 之后还需要修改一下组件里style标签的 ...

  9. Android 中数据存储方式有哪些?

    a) 文件存储b) xml,SharedPreferencec) SQLite数据库d) ContentProvidere) 网络

  10. Android中通过进程注入技术修改系统返回的Mac地址

    致谢 感谢看雪论坛中的这位大神,分享了这个技术:http://bbs.pediy.com/showthread.php?t=186054,从这篇文章中学习到了很多内容,如果没有这篇好文章,我在研究的过 ...

随机推荐

  1. Ubuntu 18.04 系统配置 NPM环境和mysql数据库问题解决

    Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. 今天我就为大家 使用 Ubun ...

  2. 通配符的匹配很全面, 但无法找到元素 'context:property-placeholder' 的声明。

    在Spring相应包导入正确的前提下,出现这个异常,是因为我们在引入命名空间的时候,没有正确引入它的DTD解析文件,以上面的context为例,解决办法如下: 在引入 xmlns:context=&q ...

  3. emoji 表情: MySQL如何支持 emoji 表情

    https://www.cnblogs.com/jentary/p/6655471.html 修改数据库字符集: ALTER DATABASE database_name CHARACTER SET ...

  4. 关于ck中断控制器

    一.中断控制器 中断控制器模块包括 其使能寄存器,状态寄存器等. 中断使能寄存器为32bit,每一个bit 对应一个中断源,具体对应到硬件上线的连接 二.cpu怎样调用到中断 (1). 前置工作 首先 ...

  5. [LeetCode] Push Dominoes 推多米诺骨牌

    There are N dominoes in a line, and we place each domino vertically upright. In the beginning, we si ...

  6. Ubuntu出现卡logo、卡住、黑屏无法正常启动、屏幕和键盘背光无法调节等一系列问题?可能是NVIDIA显卡驱动没装好

    也不知道是幸运还是不幸,我从一开始接触ubuntu就遇到这一系列的问题, 而且一直没有一个彻底解决的办法,搞得我无比头疼,也害得我重装了无数遍系统... 国际惯例,只按照个人习惯和喜好来写,对某些人来 ...

  7. 小程序block标签配合if和else 和 动态修改标题栏

    <block wx:if="{{aaaa}}"> <view>aaaa为 true,显示</view> </block> <b ...

  8. truffle unbox react 出坑指南

    最近几天差点就被这鬼东西给逼疯了,truffle init .truffle unbox webpack 不管我怎么运行都是对的,唯独truffle unbox react 不管在哪个windows都 ...

  9. LinkedBlockingQueue 注记

    近期看一个音频传输代码时,对方采用了LinkedBlockingQueue为生产者.消费者模式,来支撑读写线程. 个人感觉非常不错,因此也对这种方式进行总结,并梳理了一个基本的功能框架备用.主要两点: ...

  10. 升讯威微信营销系统开发实践:微信接口的 .NET 封装

    GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至 ...