Custom Fonts in Android

Posted by Grego on October 27, 2017

Android supports a few different typeface customizations out of the box such as italic, bold and UPPERCASE text, but how can we ship our own custom font face and use that in Android?

How

Add the font to your project

For this example I’ll use the Painter (FREE FOR PERSONAL USE) font. You can download it and follow along for the example if you want.

  1. Create a new assets folder, if you don’t have one already:
    In the Project Explorer (CMD + 1), create a New (CMD + N) FolderAssets Folder

  2. Drag and drop your font from your Finder/File Explorer onto your assets folder. If dragging and dropping directly into android studio doesn’t work, you can right click on the assets folder in the project explorer and click the Reveal in Finder or equivalent to open the directory in your OS’s native file explorer or terminal, then move the font there manually.

Programmatically assign it to your view.

In its simplest form the code looks like this:

// get a reference to the textview (or other view) you are trying to change.
final TextView exampleTextView = (TextView) findViewById(R.id.example_textview);
// create a new Typeface from our asset, second parameter must match your font name exactly
final Typeface painterTypeface = Typeface.createFromAsset(getAssets(), "Painter_PERSONAL_USE_ONLY.ttf");
// assign the typeface to our TextView.
exampleTextView.setTypeface(painterTypeface);

Clean-up and abstraction

Doing this every single time we want to change the font of a particular view is cumbersome, so what I’ve done to help code reusability and cleanliness is abstract a few things out.

Abstract font creation

First thing I did was create a new class, AppFonts to manage the creation of all the app fonts. This way when I want to change a font I can do it in one place and not have to worry about the change bubbling through my code.

I placed this class in a new package core.ui:

package com.onebigfunction.testfonts.core.ui;

import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.support.annotation.NonNull;

/**
 * Purely static class for managing the custom fonts used in the app.
 * Intentionally package private.
 */

class AppFonts {
    private static final String PAINTER_FONT = "Painter_PERSONAL_USE_ONLY.ttf";

    private AppFonts() {
        throw new AssertionError("this class is fully static!");
    }

    static Typeface regular(@NonNull final AssetManager assetManager) {
        return Typeface.createFromAsset(assetManager, PAINTER_FONT);
    }
}

Create a custom TextView class

Next, we create a custom TextView class:

package com.onebigfunction.testfonts.core.ui;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;

/**
 * Custom {@link AppCompatTextView} extension that sets a custom font face
 */

public class ObfTextView extends AppCompatTextView {
    public ObfTextView(@NonNull final Context context) {
        super(context);
        initUi();
    }

    public ObfTextView(@NonNull final Context context, @NonNull final AttributeSet attributeSet) {
        super(context, attributeSet);
        initUi();
    }

    public ObfTextView(@NonNull final Context context, @NonNull final AttributeSet attributeSet,
                       final int defStyleAttr) {
        super(context, attributeSet, defStyleAttr);
        initUi();
    }

    private void initUi() {
        setTypeface(AppFonts.regular(getContext().getAssets()));
    }
}

Note that each of these three constructors are necessary, otherwise we might crash when inflating our text view.

Pros:

  1. Do it once and forget about it

Cons:

  1. We now have to update every TextView in our app and replace it with our new class (in this case com.onebigfunction.testfonts.core.ui.ObfTextView)

  2. We have to make a new subclass for each new view we want to change the font on, which will be aggravating the very first time we do this for each new View subclass.

Possible Alternative Methods

Android 8 Fonts

As of Android 8.0 (API level 26) there is a new feature called Fonts in XML that can do something similar completely via XML. It is backwards compatible starting from API version 14 using Support Library 26.

Since it’s fairly new I have yet to test this method. I will try it at some point and update this post later with my findings.

External Libraries

There’s also a library called Calligraphy that allows you to do something similar. This was created before Android’s implementation. There is a discussion on the Calligraphy GitHub issues (although it looks more like a soliloquy) where someone mentions that it’s actually still a bit difficult with the current Android 8 fonts.

Summary

There you have it, three ways to achieve custom fonts in Android. If you’ve already tried all 3 I’d be curious to know what your preference is.

Post a comment below and let me know ;)