本文综合微信公众号「霞鹜」(lxgwshare),点击 此处 阅读原文。第一次在少数派上写文章,疏漏之处在所难免,还望各位读者多多包涵和批评指正。

由 @topjohnwu 开发的 Magisk 以其systemless(不改动系统)特性成功代替了以往的 root 神器 SuperSU,成为当前 Android 玩机爱好者的必备工具之一。通过 Magisk 我们不仅可以获取 root 权限,还可以挂载各种模块来实现系统优化或功能增强。

关联阅读:

而对一些手机美化爱好者来说,更换系统字体是一种常见的需求。但不同系统下替换字体的方式也不尽相同,比如 MIUI、EMUI 等定制 ROM 可以通过将字体文件做成主题包,通过导入主题的方式实现系统字体更换;而没有主题字体功能的手机则需要先获取 root 权限,然后才能手动对系统字体进行更换(因为字体文件一般在系统文件夹 system/fonts 里)。

在 TWRP 等第三方 recovery 出现后,字体卡刷包也出现了,它们为 root 替换字体的玩家们提供了不少便利。但这种方法不但修改了系统的文件,而且不易卸载(需要对原机字体进行备份),直到上面提到的 Magisk 的出现,才彻底改变了 Android 手机的字体更换体验——借助 Magisk 字体模块,我们可以将喜爱的字体和修改后的配置文件打包成模块,利用 Magisk 的 systemless 特性挂载达到更换系统字体的目的。模块化的字体也易于更换和卸载。

Magisk 字体模块的「得」与「失」

和上面提到的利用主题更换字体的方法相比,Magisk 字体模块最大的优势在于可以实现多字重显示和全局替换。

某些 ROM 利用主题包更换字体时,只能替换和显示一个字重且无法实现全局覆盖(如 MIUI 使用主题方法更换字体之后,Webview 还是显示为默认字体)。而用 Magisk 字体模块,这个问题就能得到解决。

左图为 MIUI 主题商店里某字体的显示效果,右图为某字体模块替换后的显示效果,可以看到用模块可以实现全局覆盖以及多字重替换。

但 Magisk 字体模块在制作上比较麻烦:我们需要将一款字体制作成多个字体文件用来替换英文、中文字体,还要修改fonts.xml描述文件来实现对多字重字体的调用。

相比而言主题包的制作更加简单,只需要一个 ttf 格式的字体和一个可以将字体打包成主题的美化软件,比 Magisk 字体模块更容易制作(而且主题替换方法无需 root 权限)。

因此自然会有人问:

有没有更简单的方法,可以将自己喜欢的 ttf 格式字体转换成 Magisk 模块,不用苦等字体模块作者手动制作吗?

为此我制作了一个字体模块模板,借助这个模块,你可以将自己喜爱的 ttf 字体打包成 Magisk 模块,实现系统字体全局替换。

字体模块模板的制作历程

以下是制作 TTF 转 Magisk 模块模板的基本原理和制作过程,如果你感兴趣的话不妨阅读了解一下。

从 fonts.xml 下手,了解系统字体调用原理

从 Android 7.0 开始,Android 系统的字体就由一个 fonts.xml 文件(在 system/etc 目录下存放)来控制。这个 XML 文件用来定义系统的默认字体,以及多语种字体的调用情况。系统利用 fonts.xml 从上往下调用文件里面指定的字体,最先调用的就是默认字体,如果默认字体缺失,可能会导致无法进入系统。

在 fonts.xml 里,最先被调用的就是系统的默认字体 Roboto 了。下面是系统默认 sans-serif 字体 Roboto 的调用语句。

Roboto-Thin.ttf

Roboto-ThinItalic.ttf

Roboto-Light.ttf

Roboto-LightItalic.ttf

Roboto-Regular.ttf

Roboto-Italic.ttf

Roboto-Medium.ttf

Roboto-MediumItalic.ttf

Roboto-Black.ttf

Roboto-BlackItalic.ttf

Roboto-Bold.ttf

Roboto-BoldItalic.ttf

再往下就是一些变体(serif、sans-serif condensed、monospace 等)的调用语句,然后就是 fallback 字体了,一般是多语种字体,family 标签后面都有所对应的语言。[下面是中日韩文字体(下称 CJK 字体)的调用语句。]

NotoSansCJK-Regular.ttc

NotoSerifCJK-Regular.ttc

NotoSansCJK-Regular.ttc

NotoSerifCJK-Regular.ttc

NotoSansCJK-Regular.ttc

NotoSerifCJK-Regular.ttc

NotoSansCJK-Regular.ttc

NotoSerifCJK-Regular.ttc

在坚果 Pro 3 发布的时候,坚果推出了方正定制的 UI 字体——Smartisan T黑。随后我收到了某个大佬分享的 Smartisan OS 7.0 字体及配置文件。在分析 Smartisan OS 字体配置的时候,发现它的默认字体是这么配置的:

Smartisan_Compact-Thin.otf

Smartisan_Compact-Light.otf

Smartisan_Compact-Regular.otf

Smartisan_Compact-Medium.otf

Smartisan_Compact-Heavy.otf

Smartisan_Compact-Bold.otf

……

Roboto-Thin.ttf

Roboto-ThinItalic.ttf

Roboto-Light.ttf

Roboto-LightItalic.ttf

Roboto-Regular.ttf

Roboto-Italic.ttf

Roboto-Medium.ttf

Roboto-MediumItalic.ttf

Roboto-Black.ttf

Roboto-BlackItalic.ttf

Roboto-Bold.ttf

Roboto-BoldItalic.ttf

也就是说,Smartisan OS 7.0 把 6 字重的 Smartisan T 黑作为系统默认调用的字体,把 Roboto 作为 fallback 字体,使 Smartisan T 黑缺字部分 fallback 到 Roboto 上,然后再往下 fallback,在调用 T 黑的同时保证不缺字(估计大多数魔改过字体的定制 ROM 一般都是这么调用的)。

我从中受到了启发,得到了 TTF 转 Magisk 模块的基本思路。

修改 fonts.xml,使其调用自定义字体1

在受到启发之后我突发奇想,假如有一个自定义的 ttf 格式的字体名叫「font.ttf」,将其放在系统的字体文件夹 system/fonts下,然后让系统默认调用这个字体,不就实现 TTF 字体更换了吗?

于是我对 fonts.xml 进行了如下修改:

将 fonts.xml 里面调用默认字体的部分进行修改:

font.ttf

在后面 fallback 字体的部分加上对 Roboto 的调用:

Roboto-Thin.ttf

Roboto-ThinItalic.ttf

Roboto-Light.ttf

Roboto-LightItalic.ttf

Roboto-Regular.ttf

Roboto-Italic.ttf

Roboto-Medium.ttf

Roboto-MediumItalic.ttf

Roboto-Black.ttf

Roboto-BlackItalic.ttf

Roboto-Bold.ttf

Roboto-BoldItalic.ttf

在调用 CJK 字体的语句前面再加上如下语句,防止西文变体在调用之后直接调用默认的思源黑体:

font.ttf

font.ttf

font.ttf

font.ttf

有些类原生 ROM 桌面会调用 Condensed 字体,为了使其调用自定义 ttf 字体,作者在调用 Condensed 语句处做了如下修改:

然后把修改之后的 fonts.xml 打包成 Magisk 模块,将其放入模块里的system/etc文件夹内,再将自定义的字体文件重命名为font.ttf放入模块的system/fonts文件夹内,然后将该模块刷入。

重启,就可以看到系统字体已经被替换成自定义的 font.ttf 了。以从 OPPO 官网下载的 OPPO Sans 为例,利用 TTF 转 Magisk 模块模板,可以将系统字体更换为 OPPO Sans,而无需修改系统字体文件。

相应地,单字重字体如果不想看到系统强制渲染加粗糊成一块的效果,可以让所有字重都调用这个 font.ttf:2

font.ttf

font.ttf

font.ttf

font.ttf

font.ttf

font.ttf

使用「防止加粗变糊」模块之后的效果。

如果是一有多个字重的字体家族,想让系统调用多个字重,可以这么改(当然必须将多字重字体按照字重等级命名为「fontw1.ttf」~「fontw9.ttf」放到 system/fonts 目录下)。3

fontw1.ttf

fontw2.ttf

fontw3.ttf

fontw4.ttf

fontw5.ttf

fontw6.ttf

fontw7.ttf

fontw8.ttf

fontw9.ttf

使用多字重模块之后的效果,前提是已按照字重将对应字体文件重命名为规定文件名。

一个新的问题

这样是能实现系统字体更换了,但是有个问题:有些字体由于自身的度量数据,以及一些字符的影响,在使用模块模板更换字体之后,可能会有偏移或者行距过大等问题(比如思源黑体/思源宋体,因为某些字符的影响,直接应用该字体会导致偏移严重)。

直接替换「思源宋体 Medium」之后造成的偏移、错位、行距过大问题

从字体层面上解决这样的问题,不仅要考虑度量,还要考虑是否有过长的字符造成这样的偏移,比较麻烦。

有一天,在极限论坛,偶然发现了极限大神「RadarNyan」(下称 R 大)分享了 ta 对于更换字体偏移的思路(帖子时间比较久远,但对 6.0 以上的 Android 仍然适用)。

RadarNyan 在极限社区分享替换字体的思路

简要说一下 R 大的思路:将系统默认字体 Roboto 的 12 个字体文件(6 个字重×2 个变体)掏空,保留其度量数据,做成 RobotoFake 文件,然后修改 fonts.xml,使系统首先调用 RobotoFake 空字体文件来控制所显示字体的度量参数,然后向下 fallback 到自定义字体文件和 Roboto;之后在中日韩文处再调用一遍自定义字体文件,然后再调用系统默认的 NotoSansCJK 来补全缺字。感兴趣的,可以点击这里了解一下详细的思路。

解决偏移4

于是,作者在模块模板的 system/fonts 目录里面加入了 R 大制作的 12 个「RobotoFake」字体文件,然后对 fonts.xml 进行了修改:

主要是在调用默认字体的语句处做如下修改:

RobotoFake-Thin.ttf

RobotoFake-ThinItalic.ttf

RobotoFake-Light.ttf

RobotoFake-LightItalic.ttf

RobotoFake-Regular.ttf

RobotoFake-Italic.ttf

RobotoFake-Medium.ttf

RobotoFake-MediumItalic.ttf

RobotoFake-Black.ttf

RobotoFake-BlackItalic.ttf

RobotoFake-Bold.ttf

RobotoFake-BoldItalic.ttf

font.ttf

Roboto-Thin.ttf

Roboto-ThinItalic.ttf

Roboto-Light.ttf

Roboto-LightItalic.ttf

Roboto-Regular.ttf

Roboto-Italic.ttf

Roboto-Medium.ttf

Roboto-MediumItalic.ttf

Roboto-Black.ttf

Roboto-BlackItalic.ttf

Roboto-Bold.ttf

Roboto-BoldItalic.ttf

多字重的修改方法可见上上一节,这里不再赘述。

经过上述优化之后,再用同样的字体,偏移问题得到了解决。使用 RadarNyan 提供的方法之后,解决偏移问题。

模块模板的获取和使用

模板下载:

包括 2.0 和 3.0 两个版本,分别包含 a(单字重版)、b(单字重防止加粗变糊版)、c(多字重版)。不懂三者区别的可返回到「字体模块模板的制作历程」一章进行了解。

单字重模块模板

将自己喜爱的 TTF 格式文件重命名为 「font.ttf」(区分大小写,otf 扩展名要改成 ttf),然后复制到模块模板里的「system/fonts」文件夹内,刷入,重启,即可看到效果。

多字重模块模板

将自己喜爱的字体家族按照字重等级重命名为「fontw#.ttf」(# 号表示 1~9 的阿拉伯数字,从 1 到 9 分别对应 Extralight、Thin、Light、Regular、Medium、Semibold、Bold、Heavy、Black 由细到粗 9 个字重,区分大小写,otf 扩展名要改成 ttf),然后复制到模块模板里的「system/fonts」文件夹内,刷入,重启,即可看到效果。

修改模块信息

可以通过修改模块里的 「module.prop」 修改模块信息。

id=lxgwttf2magisk

# 模块的 ID,只支持半角英文和数字,不能以纯数字开头

name=TTF 转 Magisk 模块模版

# 模块的名称,模块刷入后,此名称会在 Magisk Manager 里显示

version=3.0

# 模块的版本

versionCode=5

# 模块的版本代号

author=落霞孤鹜 [lxgwshare]

# 模块的作者

description=

# 这里填写模块描述,模块刷入后会在 Magisk Manager 里显示

minMagisk=17000

# 支持此模块的最低 Magisk 版本

特别注意

使用前需要解 Bootloader 锁,并刷入 Magisk。解锁过程会清除所有数据,强烈建议解锁前先备份手机里的数据。

对于某些魔改过字体的 ROM(如 MIUI11),请慎用本模块,可能会出现兼容性问题。

严禁将此模块用于商业营利用途!

结语

本文介绍了 TTF 转 Magisk 模块模板的制作原理以及使用方法,使用这个模块模板,可以使系统字体的更换变得更加方便快捷。

> 下载少数派 客户端、关注 少数派公众号,轻松玩转 Magisk 模块

android 阅读器字体,为 Android 换上任意喜欢的字体,你可以试试这个 Magisk 模块...相关推荐

  1. android xml黑体字_为 Android 换上任意喜欢的字体,你可以试试这个 Magisk 模块

    本文综合微信公众号「霞鹜」(lxgwshare),点击 此处 阅读原文.第一次在少数派上写文章,疏漏之处在所难免,还望各位读者多多包涵和批评指正. 由 @topjohnwu 开发的 Magisk 以其 ...

  2. android 阅读器自动滚动,Android编程实现小说阅读器滑动效果的方法

    本文实例讲述了Android编程实现小说阅读器滑动效果的方法.分享给大家供大家参考,具体如下: 看过小说都知道小说阅读器翻页有好多种效果,比如仿真翻页,滑动翻页,等等.由于某种原因,突然想写一个简单点 ...

  3. Android阅读器的思路(一)

    最近工作业务中遇到了,Android阅读器的需求.面临的第一个问题就是,如何根据屏幕的大小,将一本小说分成每一页需要显示的内容.简单来说,就是把一整本小说的String变成每一页恰好可以显示的Stri ...

  4. 简单开发的android阅读器源码,包含了读取数据库和文件流处理功能

    原文:简单开发的android阅读器源码,包含了读取数据库和文件流处理功能 源代码下载地址:http://www.zuidaima.com/share/1838906559466496.htm 简单地 ...

  5. 视频教程-基于NDK、C++、FFmpeg的android视频播放器开发实战-Android

    基于NDK.C++.FFmpeg的android视频播放器开发实战 夏曹俊:南京捷帝科技有限公司创始人,南京大学计算机硕士毕业,有15年c++跨平台项目研发的经验,领导开发过大量的c++虚拟仿真,计算 ...

  6. 开源能翻译英文的Android阅读器

    Filter阅读是我最近写的一个Android的阅读器,用于看英文的书(中文暂时不支持,会乱码,下一版再改). 本文章由"智障的我"原创,转载注明. http://blog.csd ...

  7. android 阅读器上下滑动_科研党利器——文石13.3寸墨水屏阅读器BOOX Max3

    此文出自知乎用户"Mars" 对 BOOX Max3 的评测,本文已征得作者授权转载. 2013年已对电纸书阅读器的种草,那个时候就有sony dpt的13.3寸大屏阅读器,鉴于穷 ...

  8. android 阅读器自动滚动,在Android手机上实现阅读器翻页效果.doc

    在Android手机上实现阅读器翻页效果 先了解各个字母表示的含义:A-把书页翻起来后看到的背面区域B-把书页翻起来后看到的下一页的一角C-当前页的可见部分.a-手指滑动页角到达的位置b-当前页翻起来 ...

  9. android adobe pdf阅读器,Adobe发布Android手机专用PDF阅读程序

    北京时间5月25日消息,据国外媒体报道,谷歌年度I/O会议上周有消息透露,Adobe已发布Android手机专用的PDF阅读程序. 使用该程序,用户可快速打开互联网下载的或电子邮件附件中的PDF文件. ...

  10. 发布一个练笔的 Android 阅读器,轻微仿91 Android 阅读器【后续将提供源码】

    由于是练笔Demo,所以界面上和优化方面并没有太多考虑,只是实现了一些基础功能和一些阅读器所必要的几个功能 阅读界面如下: 底下滚动条,模仿91阅读器的方式显示,按照文本长度百分比记算显示进度条,文本 ...

最新文章

  1. python精彩编程200例pdf下载-最经典的25本Python编程开发电子书(附下载地址)!...
  2. 远程计算机未能及时反应,Win10无法打开软件提示“服务器没有及时响应或控制请求”怎么办...
  3. Linux软件安装小结
  4. pagerank公式的理解
  5. thinkphp 5 stdClass Call to undefined
  6. 聊一聊ABP vNext的模块化系统
  7. 服务器集成显卡性能,Win8.1与Ubuntu 14.10:集成显卡性能PK
  8. CreateIoCompletionPort和完成端口
  9. Sublime Text 一键删除空白行的方法
  10. 【neo4j】知识图谱实战---构建红楼梦知识图谱
  11. Stata:终极匹配ultimatch
  12. 有关“安装程序启动安装引擎失败:不支持此接口”错误的解决方法
  13. 两个60后大叔的新能源战争:王传福与曾毓群的万亿赌局
  14. Informix 常用函数一
  15. 链家网爬取深圳租房分析
  16. 语音模块:pyttsx变声项目
  17. 让Linux内核不再卡死在DHCP请求上
  18. 创建自己第一个安卓程序_从一天创建和发布我的第一个应用程序中学到的东西...
  19. 费雪MOGAFX方程式是什么?(三)
  20. 2022年计算机软件水平考试信息系统项目管理(高级)练习题及答案

热门文章

  1. 良心安利三大游戏音效素材网站
  2. 纯净版Windows7系统迅雷下载路径
  3. Qt调用Com组件--QT调用COM组件DLL(dumpCPP工具)
  4. strcmp函数原型 C语言
  5. 【Java】URL下载网络资源(CloudMusic)
  6. 高等数学——常用不定积分公式
  7. 安卓屏幕朗读app_安卓车机后装苹果CarPlay盒子的自动化分享
  8. USB 公,母头接口
  9. jar包解压的文件重新打包成jar文件
  10. C++语言对C语言的扩展(二)