在大多手机上可以通过android.graphics.Typeface#createFromFile(java.lang.String)
方法创建一个Typeface实例;但有些ROM需要通过反射方法实现创建Typeface实例。
Typeface typeface = Typeface.createFromFile(path); // 创建Typeface实例
textView.setTypeface(typeface); // 设置到TextView
对于通用方法失效的情况,通过反射方法调用Typeface及FontFamily相关方法,进而绕过ROM修改的设置字体方法,创建Typeface;而FontFamily类方法在不同Android版本的实现有一定的不同,因此反射方案也有多种。对于API≤20时,可按通用方法处理。经过对非公开SDK的尝试,逐步发现了以下的反射方案。
依次反射调用以下方法
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight, int italic)
android.graphics.FontFamily#allowUnsupportedFont()
android.graphics.FontFamily#freeze()
android.graphics.Typeface#nativeCreateFromArray(long[] familyArray, int weight, int italic)
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path, int ttcIndex)
android.graphics.Typeface#nativeCreateFromArray(FontFamily[] families)
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path)
android.graphics.Typeface#nativeCreateFromArray(FontFamily[] families)
此方案与7.x方案相比,调用方法名相同,但addFont的参数略有不同。但实现后发现在部分ROM中仍失效。经过分析,在华为ROM5.x~6.x中,对Typeface#init的方法也进行了屏蔽,因此实现了另一种方案。
android.graphics.FontFamily#nCreateFamily(String lang, int variant) // 创建FontFamily实例,取到mNativePtr
android.graphics.FontFamily#nAddFont(long nativeFamily, String path) // 创建Font
android.graphics.Typeface#nativeCreateFromArray(long[] familyArray) // 创建Typeface
android.graphics.Typeface#Typeface(long ni) // 构造Typeface实例
后续又经过尝试发现,在7.x~8.x的厂商ROM中,只调用Typeface#init()
方法,重新初始化之后即可直接调用Typeface#createFromFile()
方法创建Typeface实例;但5.x~6.x仍需使用原方案。总结方案如下:
android.graphics.Typeface#init()
Typeface typeface = Typeface.createFromFile(path); // 创建Typeface实例
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path)
android.graphics.Typeface#nativeCreateFromArray(FontFamily[] families)
Typeface typeface = Typeface.createFromFile(path); // 创建Typeface实例
在Android P(API 28)中,Google开始收拢对非公开API的使用,前述反射方法在Google公布的浅灰名单中,在Android P中仍可调用,但存在不能调用的风险,可考虑向Google申请加白名单。
另外,使用反射方案创建的Typeface缺少sFallbackFonts,导致当创建的字库中缺少某字时,无法使用系统提供的回落字库绘制,显示为空白。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。