Skip to content

Instantly share code, notes, and snippets.

@orwir
Created June 3, 2016 11:33
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save orwir/6df839e3527647adc2d56bfadfaad805 to your computer and use it in GitHub Desktop.
Save orwir/6df839e3527647adc2d56bfadfaad805 to your computer and use it in GitHub Desktop.
Android: change fonts for the whole application
public class FontsReplacer {
@SuppressWarnings("unchecked")
public static void replaceFonts(Context context) {
try {
//we need to change all static fields contains fonts:
//1. static constants
setStaticFinalField(Typeface.class, "DEFAULT", FontCache.getTypeface(context, Typeface.NORMAL));
setStaticFinalField(Typeface.class, "DEFAULT_BOLD", FontCache.getTypeface(context, Typeface.BOLD));
setStaticFinalField(Typeface.class, "SANS_SERIF", FontCache.getTypeface(context, Typeface.NORMAL));
setStaticFinalField(Typeface.class, "SERIF", FontCache.getTypeface(context, Typeface.NORMAL));
setStaticFinalField(Typeface.class, "MONOSPACE", FontCache.getTypeface(context, Typeface.NORMAL));
//2. array with defaults
setStaticFinalField(Typeface.class, "sDefaults", new Typeface[] {
Typeface.DEFAULT,
Typeface.DEFAULT_BOLD,
FontCache.getTypeface(context, Typeface.ITALIC),
FontCache.getTypeface(context, Typeface.BOLD_ITALIC)
});
//3. invoke method 'setDefault'
Method setDefault = Typeface.class.getDeclaredMethod("setDefault", Typeface.class);
setDefault.setAccessible(true);
setDefault.invoke(null, Typeface.DEFAULT);
//4. replace fonts in the map
Field sSystemFontMapField = Typeface.class.getDeclaredField("sSystemFontMap");
sSystemFontMapField.setAccessible(true);
Map<String, Typeface> sSystemFontMap = (Map<String, Typeface>) sSystemFontMapField.get(null);
for (String key : sSystemFontMap.keySet()) {
sSystemFontMap.put(key, FontCache.getDefaultTypeface(context));
}
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
}
private static void setStaticFinalField(Class clazz, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
try {
Field modifiers = Field.class.getDeclaredField("accessFlags");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
field.set(null, value);
}
private FontsReplacer() {}
}
@praveen2gemini
Copy link

If we use reflections to achieve this, Will google play store reject the app during publishing?

@orwir
Copy link
Author

orwir commented May 11, 2020

If we use reflections to achieve this, Will google play store reject the app during publishing?

Hi. Nope. But this solution pretty old and I wouldn't recommend it anyway. Custom fonts supported now out of the box.

@jamshadinho
Copy link

is it possible to replace system font? i am not setting typeface in styles, my requirement is based on some parameter i need to set font, if the parameter is not set i need to set android system font. is that possible?

@orwir
Copy link
Author

orwir commented Aug 17, 2021

@jamshadinho this one is obsolete. Custom fonts supported now of of the box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment