android中可能会遇到修改字体的情况,虽然说需求比较少,但是偶尔还会遇到
可以使用三方框架来帮助我们简单做到
api "uk.co.chrisjenx:calligraphy:2.2.0"
在style文件中添加一个字体的style
<style name="core_TextAppearance.RobotoThinPath" parent="android:TextAppearance">
<item name="fontPath">fonts/Roboto-Thin.ttf</item>
</style>
我app中的main/assert/fonts/Roboto-hin.ttf 放置字体文件
AS集成这个框架,在activity的 attachBaseContext(Context newBase)方法中添加我们修改后的字体的context
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
为什么要在attachBaseContext中添加呢? 我们都知道activity中是有context的,但是context是怎么来的呢?
activity的构造方法是无参构造,所以不是通过构造方法传递的吗?
activity的集成流程 context(抽象类) -> ContextWrapper(实现了context的所有方法,service的父类) -> ContextThemeWrapper(带主体的context) -> activity
再看下activity的启动流程 : activity启动是先执行了 attach方法 下面才回去执行onCreate 如果我们想把一些初始化放到最高的优先级,可以放在 attachBaseContext中。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
} catch (Exception e) {
}
try {
if (activity != null) {
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
attachBaseContext到底干了什么呢? 代码其实很简单,就是把context赋值给activity,所以我们在把newbase添加了字体,所以activity的context,都会有我们的字体效果。
需要注意一点,就是每一个界面都有一个context,所以建议写一个baseActivity,直接继承。
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}