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

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

期待你持续关注。

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

  • Android 字体修改概述|开篇
  • 修改字体需要了解 Typeface 的所有细节
  • 简单粗暴的方式,修改字体
  • 利用反射,修改全局字体
  • 利用 AppCompatDelegate ,全局替换全局字体
  • 通过修改 LayoutInflater,全局替换字体!
  • 自定义属性,支持多个字体文件!
  • Android 可下载字体,Font in xml!

一、前言

之前已经介绍了很多种,快速、低入侵的替换全局字体的方式。但是大多数情况下,我们需要实现的功能,一定已经有现成的实现方案。

本文就介绍一个 Github 上,比较火的全局替换字体的开源库,差不多阅读文档加集成,一个小时全局替换字体不是梦。

这个开源替换字体库就是 Calligraphy:

https://github.com/chrisjenx/...

二、如何使用Calligraphy

既然是要接入开源库来全局替换字体,先来看看它可以实现的效果。

接下来,我们开始一步步集成它。

2.1 添加 Gradle 依赖

Calligraphy 支持 Gradle 和 jar 的接入方式,这里使用 Gradle 来接入。

2.2 添加字体文档到项目内

Calligraphy 支持的文件,可以放在 assets/ 目录下,当然,我们可以再在其中建立一个文件夹来专门的存放字体文件。

2.3 初始化 Calligraphy

Calligraphy 使用 CalligraphyConfig 类,来进行初始化。它需要在 App 的入口,Application.onCreate() 中调用。

初始化主要是为了指定一些默认的配置,例如:默认字体、默认属性值。

2.4 替换 Context

Calligraphy 对 Activity 的 Context,进行了一次包装,需要使用它包装的 Context,才可以达到替换字体的效果。所以还需要重写 BaseActivity 中的 attachBaseContext() 方法,将其替换成 Calligraphy 为我们提供的 Context 的包装类 CalligraphyContextWrapper。

2.5 使用 Calligraphy

到这里,就完成了 Calligraphy 的配置了,我们只需要在 TextView 中,通过属性去使用它就好了,它配置的是我们字体文件,在 assets 目录下的路径。

2.6 查缺补漏

Calligraphy 使用起来还是很方便的,并且也支持更多的配置方式,例如: Style、Theme 都可以。

具体的使用细节,大家还是阅读文档了解更方便。

三、Calligraphy的原理

我们使用一个开源库,当然要理解它的原理才能放心使用在商业项目上,接下来,我们就来分析一下 Calligraphy 的实现原理,看看和之前介绍的方式,有没有什么区别。

先来看看 Calligraphy 的整体结构。

可以看到,它一共需要的类非常的少,算是一个比较精简的库了,并且它并没有重写 TextView ,所以应该是通过其它的方式来做到字体的替换的。

我们先来看看在 Application 需要调用的配置类, CalligraphyConfig 的源码。

CalligraphyConfig 使用 Builder 的模式去初始化自己,可以看到这里只是设置了一些配置项,并没有实际的业务逻辑。

CalligraphyConfig 初始化之后,就以静态变量存储起来,供其它地方使用,是一种单例的模式,但是并没有考虑线程安全的问题。

既然 CalligraphyConfig 没有实际的逻辑,那么接下去应该如何追踪重要的代码呢?

仔细观察之前配置项里,需要重写 Activity.attachBaseContext() 方法,这里会传递它重写的一个 Context 的包装类 CalligraphyContextWrapper,所以接下来我们再看看 CalligraphyContextWrapper 的源码逻辑。

读了 CalligraphyContextWrapper 源码之后,你会发现它最重要的就是重写了 getSystemService() 方法,当它是 LAYOUT_INFLATER_SERVICE 的时候,将自己的 CalligraphyLayoutInflater 类,返回回去。

那么,这里的 LAYOUT_INFLATER_SERVICE 到底是什么呢?

我想大家应该对 LayoutInflater 不陌生,从 layout-xml 加载 View 的时候,都需要用到它,相信下面这段代码,应该大家都不陌生。

再仔细看看 LayoutInflater.from() 方法的源码。

可以看到,这里获得 LayoutInflater 对象的时候,用到的就是 LAYOUT_INFLATER_SERVICE。

所以 CalligraphyContextWrapper.getSystemService() 方法被重写的目的,就是为了替换掉 LayoutInflater 对象,所以可以猜想,设置自定义字体的地方,就在自定义的 LayoutInflater 中。

继续查看 CalligraphyLayoutInflater 的源码,最终修改字体的逻辑,是在 CalligraphyContextWrappe 的 onViewCreatedInternal() 方法里面。

它会取出我们自定义属性上设置的值,然后设置到初始化好的 TextView 上去。

四、Calligraphy 小结

到此就完成了 Calligraphy 的主要逻辑追踪,几个核心技术点:

  1. Calligraphy 不需要重写 TextView 之类的控件。
  2. Calligraphy 重写了 LayoutInflater 。
  3. Calligraphy 在 attachBaseContext() 方法中,替换掉 ContextWrapper。
  4. 又通过自定义的 ContextWrapper 的 getSystemService() 方法,将 LayoutInflater 替换成库里重写的 CalligraphyLayoutInflater。
  5. 在 CalligraphyLayoutInflater 中,拦截我们需要的 TextView 和其子类,对它们的字体替换成我们设置的字体。

当然,实际上,开源库之所以可以流传的比较广,它还做了更多的细节处理,但是我们一般分析开源库,只需要关心主线逻辑就可以了。

整体来说 Calligraphy 没有什么大毛病,可以放心使用,当然如果你用了一些同样依赖此原理的第三方库,可能会有冲突,这个就只能具体问题具体分析了。

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法。Web项目源码。

推荐阅读:

  • Glide 这样用,更省内存!!!
  • 跳槽前,不思考这些等于白跳!!!
  • 哪些年熬过的夜,终将会"回报"你的
  • 当你只有一个设备的时候,如何做好屏幕适配
  • Android 源码,在线阅读更方便!!!

点赞或者分享吧~

全局替换字体,开源库更方便!!!相关推荐

  1. 全局替换字体的 4 种方式

    前言 很高兴遇见你~ 在本系列的上一篇文章中,我们了解了 Xml 中的字体,还没有看过上一篇文章的朋友,建议先去阅读 Android字体系列 (三):Xml中的字体,有了前面的基础,接下来我们就看下 ...

  2. android 全局换字体,Android 全局替换字体

    1. 替换全局字体 需要引入依赖 // 替换全局字体使用 api 'com.android.support:support-v13:28.0.0' 在 res 目录下创建一个 font 目录,将用到的 ...

  3. Windows系统全局替换字体总结

    Win+R,输入regedit,按HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Fonts路径打开,右侧双击Micros ...

  4. Android 替换字体的方式以及同时替换多种字体

    替换字体的方式 1.Android原生的适配方案:按照区域(values-ko values-it-rIT values-zh-rCN) 按照机器的Android版本 按照设备分辨率来加载不同的fon ...

  5. Android开发替换字体

    为满足app个性的需求,有时候需要使用一些个性字体.这时候就需要替换默认的字体了. 首先,Android为我们提供了四种字体可选:normal.sans.serif.monospace. 使用方式: ...

  6. android反射替换字体,快速使用反射更换Android全局字体

    问题背景 之前在编写鲤鱼日语时,因为使用了外部的字体,这导致了一个问题就是我的ListView显示的是圆滑的字体,但是其他dialog.Spinner就全都是Android默认字体,这样不统一就会很难 ...

  7. 推荐一个开源库(Calligraphy)将ttf字体库加入到项目中,轻松实现各种字体

    库连接(https://github.com/chrisjenx/Calligraphy) 官方截图 详细使用说明请进入该链接查看, 下面简单介绍其中的一种用法,设置到主题(Theme)中 第一步:将 ...

  8. 【踩坑速记】开源日历控件,顺便全面解析开源库打包发布到Bintray/Jcenter全过程(新),让开源更简单~...

    一.写在前面 自使用android studio开始,就被它独特的依赖方式:compile 'com.android.support:appcompat-v7:25.0.1'所深深吸引,自从有了它,麻 ...

  9. Android开源项目以及开源库集合(持续更新中)

    UI Awesome-MaterialDesign – MaterialDesignCenter改名为Awesome-MaterialDesign,优化了布局,新增了不少库. awesome-andr ...

最新文章

  1. jquery选择器之基本筛选器
  2. LINUX 下构建OpenGL ES 3.0
  3. window10 vs2013 SIFTGPU
  4. 删除vss文件批处理
  5. 110. Balanced Binary Tree
  6. mysql005约束.列级别
  7. Jsoup从元素中抽取属性 文本和HTML
  8. h5 uniapp history模式下刷新页面404
  9. Linux 信号(signal)
  10. python爬取北京政务公开惠民地图信息
  11. 【AndroidStudio】手机QQ登录界面2022版
  12. SFP光模块接口说明
  13. 计算机文件丢失不能正常启动,电脑说文件丢失或损坏开不了机怎么办?
  14. 父爱动画代码python_python表白实现代码(可视化与动画版)
  15. c语言表达ch是大写英文字母,做几道C语言的习题!
  16. Lumen (Laravel子框架) 简介及分析
  17. 练习- Java顺序结构综合练习三之金融投资收益计算
  18. 判别一个分解的无损连接性
  19. 学生学习成绩下降,家长应该怎么帮助学生进步?
  20. efk-elastalert-alerta集中日志自动告警

热门文章

  1. boost::function_types::is_function_pointer用法的测试程序
  2. Boost : to_string_stub用法的测试程序
  3. boost::callable_traits的has_varargs的测试程序
  4. VTK:可视化算法之VelocityProfile
  5. VTK:可视化之MultipleViewports
  6. VTK:Utilities之BrownianPoints
  7. VTK:结构化网格之StructuredGrid
  8. VTK:Rendering之StringToImageDemo
  9. VTK:网格之QuadricDecimation
  10. OpenCV使用dnn从图像中解析人体部位的实例(附完整代码)