前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中使用反射方法创建Typeface实例

Android中使用反射方法创建Typeface实例

原创
作者头像
fdroid
发布2019-01-08 15:03:55
1.5K0
发布2019-01-08 15:03:55
举报
文章被收录于专栏:Android填坑指南

背景

在大多手机上可以通过android.graphics.Typeface#createFromFile(java.lang.String)方法创建一个Typeface实例;但有些ROM需要通过反射方法实现创建Typeface实例。

1. 通用方法

代码语言:txt
复制
Typeface typeface = Typeface.createFromFile(path);	// 创建Typeface实例
textView.setTypeface(typeface);					// 设置到TextView

2. 反射方法

对于通用方法失效的情况,通过反射方法调用Typeface及FontFamily相关方法,进而绕过ROM修改的设置字体方法,创建Typeface;而FontFamily类方法在不同Android版本的实现有一定的不同,因此反射方案也有多种。对于API≤20时,可按通用方法处理。经过对非公开SDK的尝试,逐步发现了以下的反射方案。

1) Android 8.x (API 26, 27)

依次反射调用以下方法

代码语言:txt
复制
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)
2) Android 7.x (API 24, 25)
代码语言:txt
复制
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path, int ttcIndex)
android.graphics.Typeface#nativeCreateFromArray(FontFamily[] families)
3) Android 5.x 6.x (API 21, 22, 23)
代码语言:txt
复制
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的方法也进行了屏蔽,因此实现了另一种方案。

代码语言:txt
复制
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实例

3. 最终方案

后续又经过尝试发现,在7.x~8.x的厂商ROM中,只调用Typeface#init()方法,重新初始化之后即可直接调用Typeface#createFromFile()方法创建Typeface实例;但5.x~6.x仍需使用原方案。总结方案如下:

1) Android 7.x~8.x (API 24~27)
代码语言:txt
复制
android.graphics.Typeface#init()
Typeface typeface = Typeface.createFromFile(path);	// 创建Typeface实例
2) Android 5.x~6.x (API 21~23)
代码语言:txt
复制
android.graphics.Typeface#init()
android.graphics.FontFamily#addFont(String path)
android.graphics.Typeface#nativeCreateFromArray(FontFamily[] families)
3) Android 4.x (API 15~20)及通用方法
代码语言:txt
复制
Typeface typeface = Typeface.createFromFile(path);	// 创建Typeface实例

4. Android P

在Android P(API 28)中,Google开始收拢对非公开API的使用,前述反射方法在Google公布的浅灰名单中,在Android P中仍可调用,但存在不能调用的风险,可考虑向Google申请加白名单。

5.其他

另外,使用反射方案创建的Typeface缺少sFallbackFonts,导致当创建的字库中缺少某字时,无法使用系统提供的回落字库绘制,显示为空白。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 1. 通用方法
  • 2. 反射方法
    • 1) Android 8.x (API 26, 27)
      • 2) Android 7.x (API 24, 25)
        • 3) Android 5.x 6.x (API 21, 22, 23)
        • 3. 最终方案
          • 1) Android 7.x~8.x (API 24~27)
            • 2) Android 5.x~6.x (API 21~23)
              • 3) Android 4.x (API 15~20)及通用方法
              • 4. Android P
              • 5.其他
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档