How to Set a Custom Font in the ActionBar Title?

user742030 picture user742030 · Dec 22, 2011 · Viewed 148.1k times · Source

How (if possible) could I set a custom font in a ActionBar title text(only - not the tab text) with a font in my assets folder? I don't want to use the android:logo option.

Answer

twaddington picture twaddington · Mar 3, 2013

You can do this using a custom TypefaceSpan class. It's superior to the customView approach indicated above because it doesn't break when using other Action Bar elements like expanding action views.

The use of such a class would look something like this:

SpannableString s = new SpannableString("My Title");
s.setSpan(new TypefaceSpan(this, "MyTypeface.otf"), 0, s.length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

// Update the action bar title with the TypefaceSpan instance
ActionBar actionBar = getActionBar();
actionBar.setTitle(s);

The custom TypefaceSpan class is passed your Activity context and the name of a typeface in your assets/fonts directory. It loads the file and caches a new Typeface instance in memory. The complete implementation of TypefaceSpan is surprisingly simple:

/**
 * Style a {@link Spannable} with a custom {@link Typeface}.
 * 
 * @author Tristan Waddington
 */
public class TypefaceSpan extends MetricAffectingSpan {
      /** An <code>LruCache</code> for previously loaded typefaces. */
    private static LruCache<String, Typeface> sTypefaceCache =
            new LruCache<String, Typeface>(12);

    private Typeface mTypeface;

    /**
     * Load the {@link Typeface} and apply to a {@link Spannable}.
     */
    public TypefaceSpan(Context context, String typefaceName) {
        mTypeface = sTypefaceCache.get(typefaceName);

        if (mTypeface == null) {
            mTypeface = Typeface.createFromAsset(context.getApplicationContext()
                    .getAssets(), String.format("fonts/%s", typefaceName));

            // Cache the loaded Typeface
            sTypefaceCache.put(typefaceName, mTypeface);
        }
    }

    @Override
    public void updateMeasureState(TextPaint p) {
        p.setTypeface(mTypeface);

        // Note: This flag is required for proper typeface rendering
        p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.setTypeface(mTypeface);

        // Note: This flag is required for proper typeface rendering
        tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
    }
}

Simply copy the above class into your project and implement it in your activity's onCreate method as shown above.