版权说明:本文为 开开向前冲 原创文章,转载请注明出处;
注:限于作者水平有限,文中有不对的地方还请指教
背景: 最近在做一个智能POS项目,Android 平台:L,系统需要的字库Android 默认没有,需要添加到系统;
我们平时开发中,很少去使用特定的字体,但是字体却存在于我们系统中,如何针对特定的文本指定特定的字库呢?
public class MainActivity extends AppCompatActivity {
TextView textView1;
TextView textView2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);//activity_main.xml 里面只有两个TextView,ID为tx1,tx2;
textView1 = (TextView) findViewById(R.id.tx1));
textView2 = (TextView) findViewById(R.id.tx2));
textView1.setText("Hello World");
textView2.setText("Hello World");
textView1.setTypeface(Typeface.create("AvenirNextCondensed",Typeface.NORMAL));//AvenirNextCondensed是我添加的字库
textView2.setTypeface(Typeface.create("simkai",Typeface.NORMAL));
}
}
activity_main.xml很简单,篇幅原因就不贴代码了;
对,你没看错,字体的设置就是这么简单,控件可以直接使用,和使用setText()方法的使用一样;对于这个字库是如何添加呢?我刚接到任务时也不清楚,Google 了一下,在Stack Overflow 上找到一篇android-add-custom-fonts-to-system;正常这篇文章主要是讲解如何将字库文件(.ttf)编译到/system/fonts目录,还需要参考系统字库的配置方式修改
/frameworks/base/data/fonts/system_fonts.xml
/frameworks/base/data/fonts/fallback_fonts.xml
/frameworks/base/data/fonts/fonts.xml
但是当我根据文章把一切配置OK后,编写上面测试程序,发现竟然无效;因为android-add-custom-fonts-to-system文章中少配置了一个文件; frameworks/base/data/fonts/fonts.xml
这里我说一下添加字库到系统的完整步骤:
1:Copy 自己添加的字体库文件(后缀是.ttf)到目录 frameworks/base/data/fonts
2:Modify framworks/base/data/fonts/Android.mk
3:Modify frameworks/base/data/fonts/fonts.mk
4:Modify frameworks/base/data/fonts/system_fonts.xml
5:Modify frameworks/base/data/fonts/fallback_fonts.xml
6:Modify frameworks/base/data/fonts/fonts.xml
步骤一:
拷贝文件这个很简单,不需要细说,记住需要到的目录就好;
步骤二:
Modify framworks/base/data/fonts/Android.mk
在font_src_files 中添加需要编译的字体库名字:
font_src_files := \
Roboto-Regular.ttf \
Roboto-Bold.ttf \
...
simsun.ttc \
simkai.ttf \
msyh.ttf \
impact-Regular.ttf \
AvenirNextCondensed-Bold.ttf \
PosSong-8.ttf \
PosSong-16.ttf \
PosSong-24.ttf \
simfang.ttf
步骤三:
Modify frameworks/base/data/fonts/fonts.mk
在PRODUCT_PACKAGES下添加需要编译的字体库名字:
PRODUCT_PACKAGES := \
DroidSansFallback.ttf \
Roboto-Regular.ttf \
......
simsun.ttc \
simkai.ttf \
msyh.ttf \
impact-Regular.ttf \
AvenirNextCondensed-Bold.ttf \
PosSong-8.ttf \
PosSong-16.ttf \
PosSong-24.ttf \
simfang.ttf
步骤四:
Modify frameworks/base/data/fonts/system_fonts.xml
下面对应用使用应用内部Assets资源与调用系统的字体库方式进行比较:
textView1.setTypeface(Typeface.create("simkai",Typeface.NORMAL));//调用系统
textView1.setTypeface(Typeface.createFromAsset(this.getAssets(),"simkai.ttf"));//调用应用内部Assets资源
从上面代码差异我们就知道,调用系统的时候不需要使用具体执行一个具体的ttf(simkai.ttf)库文件,但是需要指定一个具体的名字("simkai"),其实这个名字就是("simkai")就是指向了simkai.ttf 文件,那这个名字和具体的字体库文件是如何关联的吗(看着就像把字体库的全名(simkai.ttf)去掉.ttf的后缀得到的(simkai))?那具体是不是这样呢?答案是否定的,只是我们习惯的配置方式是这样配置而已,至于具体的配置在那里呢?
frameworks/base/data/fonts/system_fonts.xml
在该文件中添加字体库的nameset和fileset对应关系;
<family>
<nameset>
<name>simkai</name>
</nameset>
<fileset>
<file>simkai.ttf</file>
</fileset>
</family>
<family>
<nameset>
<name>AvenirNextCondensed</name>
</nameset>
<fileset>
<file>AvenirNextCondensed-Bold.ttf</file>
</fileset>
</family>
看到没,这里simkai的nameset指向了simkai.ttf的fileset。你也可以根据你自己的名字来命名;
步骤5:
Modify frameworks/base/data/fonts/fallback_fonts.xml
在该文件中添加字体库文件的fileset
<family>
<fileset>
<file>simkai.ttf</file>
</fileset>
</family>
<!-- add for msyh-->
<family>
<fileset>
<file>msyh.ttf</file>
</fileset>
</family>
<family>
<fileset>
<file>impact-Regular.ttf</file>
</fileset>
</family>
<family>
<fileset>
<file>AvenirNextCondensed-Bold.ttf</file>
</fileset>
</family>
步骤6:
Modify frameworks/base/data/fonts/fonts.xml
配置系统库字体,在Android 5.1中必须配置,相同字体库文件的 family name 必须和和前面system_fonts.xml文件中的nameset一致(理论上一致,有兴趣的读者可以尝试不一致,我没有试过),textView1.setTypeface(Typeface.create("simkai",Typeface.NORMAL));
<family name="simkai">
<font weight="400" style="normal">simkai.ttf</font>
</family>
<family name="msyh">
<font weight="400" style="normal">msyh.ttf</font>
</family>
<family name="impact">
<font weight="400" style="normal">impact-Regular.ttf</font>
</family>
<family name="simfang">
<font weight="400" style="normal">simfang.ttf</font>
</family>
<family name="AvenirNextCondensed">
<font weight="400" style="normal">AvenirNextCondensed-Bold.ttf</font>
</family>
特别注意:我们修改了这几个文件还需要注意一些编译细节,比如上述几个.xml文件都会被编译到/system/etc/目录下,但是我在Android 5.1 中编译了却有一个文件没有生效,那就是fonts.xml,经过比较,我发现系统中的fonts.xml没有我添加的内容,经过在系统中查找,发现了猫腻:
vendor/qcom/proprietary/qrdplus/globalization/engine目录下的Android.mk文件中有如下语句:
include $(CLEAR_VARS)
LOCAL_MODULE := fonts.xml
LOCAL_SRC_FILES := fonts-Rev.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc
include $(BUILD_PREBUILT)
上面这个代码的意思是把fonts-Rev.xml 编译到编译成fonts.xml,拷贝到/system/etc目录下;看到这里就知道为什么我的修改没生效了吧;我的修改先编译到/system/etc目录下,然后被这个fonts-Rev.xml编译的fonts.xml覆盖了(经过对比发现编译出来的/system/etc/fonts.xml果真和这个fonts-Rev.xml一模一样);两种解决办法:1,将我的修改添加到vendor/qcom/proprietary/qrdplus/globalization/engine目录下的fonts-Rev.xml;2,在vendor/qcom/proprietary/qrdplus/globalization/engine的Android.mk中将上面的那几行代码注释掉;