Is it possible to set a custom font for entire of application?
I need to use certain font for my entire application. I have .ttf file for the same. Is it possible to set this as default font, at application start up and then use it elsewhere in the application? When set, how do I use it in my layout XMLs?
Solution 1:
Yes with reflection. This works (based on this answer):
(Note: this is a workaround due to lack of support for custom fonts, so if you want to change this situation please do star to up-vote the android issue here). Note: Do not leave "me too" comments on that issue, everyone who has stared it gets an email when you do that. So just "star" it please.
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Typeface;
public final class FontsOverride {
public static void setDefaultFont(Context context,
String staticTypefaceFieldName, String fontAssetName) {
final Typeface regular = Typeface.createFromAsset(context.getAssets(),
fontAssetName);
replaceFont(staticTypefaceFieldName, regular);
}
protected static void replaceFont(String staticTypefaceFieldName,
final Typeface newTypeface) {
try {
final Field staticField = Typeface.class
.getDeclaredField(staticTypefaceFieldName);
staticField.setAccessible(true);
staticField.set(null, newTypeface);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
You then need to overload the few default fonts, for example in an application class:
public final class Application extends android.app.Application {
@Override
public void onCreate() {
super.onCreate();
FontsOverride.setDefaultFont(this, "DEFAULT", "MyFontAsset.ttf");
FontsOverride.setDefaultFont(this, "MONOSPACE", "MyFontAsset2.ttf");
FontsOverride.setDefaultFont(this, "SERIF", "MyFontAsset3.ttf");
FontsOverride.setDefaultFont(this, "SANS_SERIF", "MyFontAsset4.ttf");
}
}
Or course if you are using the same font file, you can improve on this to load it just once.
However I tend to just override one, say "MONOSPACE"
, then set up a style to force that font typeface application wide:
<resources>
<style name="AppBaseTheme" parent="android:Theme.Light">
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="android:typeface">monospace</item>
</style>
</resources>
API 21 Android 5.0
I've investigated the reports in the comments that it doesn't work and it appears to be incompatible with the theme android:Theme.Material.Light
.
If that theme is not important to you, use an older theme, e.g.:
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<item name="android:typeface">monospace</item>
</style>
Solution 2:
There is a great library for custom fonts in android:Calligraphy
here is a sample how to use it.
in Gradle you need to put this line into your app's build.gradle file:
dependencies {
compile 'uk.co.chrisjenx:calligraphy:2.2.0'
}
and then make a class that extends Application
and write this code:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("your font path")
.setFontAttrId(R.attr.fontPath)
.build()
);
}
}
and in the activity class put this method before onCreate:
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
and the last thing your manifest file should look like this:
<application
.
.
.
android:name=".App">
and it will change the whole activity to your font! it's simple and clean!