In standard, Android offers a simple font for all views that display texts to the screen. Effect is great but sometimes you could want customize your application by using your specific font and offers to your users an awesome effect. To achieve that, you need to load the specific font and install it on your View. This article show you how to set a particular font for a Button or a TextView on Android with an elegant solution reducing memory usage.

First step is to get your font at the ttf format and put it on the assets folder of your Android project. Here, we want a digital effect, so we put our digital.ttf font on assets.

To reduce memory usage, we are going to use a FontCache in charge to manage fonts loaded from assets. Code for that cache is pretty simple :


public class FontCache {

 private static Hashtable<String, Typeface> fontCache = new Hashtable<String, Typeface>();

 public static Typeface get(String name, Context context) {
   Typeface tf = fontCache.get(name);

   if(tf == null) {
      try {
         tf = Typeface.createFromAsset(context.getAssets(), name);
      } catch (Exception e) {
        return null;
      }

      fontCache.put(name, tf);
   }

   return tf;
 }
}

To create an elegant solution, we are going to let developers to set font directly in XML style file. For example, we would like to create a digitalButton style like that in res/values/style.xml :


<style name="digitalButton" parent="@android:style/Widget.Button">
   <item name="font">fonts/digital.ttf</item>
</style>

To get the item value of font in Java code, we need to add a res/value/attrs.xml file with following declaration :


<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="CustomFont">
   <attr name="font" format="string"/>
 </declare-styleable>
</resources>

Then, we can create a CustomFontHelper to get the value from style file :


public class CustomFontHelper {

 public static void setCustomFont(TextView textview, Context context, AttributeSet attrs) {
   TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomFont);
   String font = a.getString(R.styleable.CustomFont_font);
   setCustomFont(textview, font, context);
   a.recycle();
 }

 public static void setCustomFont(TextView textview, String font, Context context) {
   if(font == null) {
    return;
   }

   Typeface tf = FontCache.get(font, context);

   if(tf != null) {
    textview.setTypeface(tf);
   }
 }

}

Now, we can define our DigitalButton by extending Android standard Button. Only difference is in constructors where we must take attributes setted to Button and load the font defined in style applied. DigitalButton implementation is like that :


public class DigitalButton extends Button {

 public DigitalButton(Context context) {
    super(context);
 }

 public DigitalButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    CustomFontHelper.setCustomFont(this, context, attrs);
 }

 public DigitalButton(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    CustomFontHelper.setCustomFont(this, context, attrs);
 }
}

Last step is to use our DigitalButton in a layout for an activity :


<com.ssaurel.mySokoban.DigitalButton
   style="@style/digitalButton"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@string/play"/>

Result can be seen with the following screenshot where buttons are awesome digital buttons :

DigitalButton

Obviously, this elegant solution can be used with text views by overriding standard TextView object and by calling CustomFontHelper static method in constructors.