Custom and Downloadable Fonts on Android

See how to make great looking apps using the new custom and downloadable fonts capability available in Android Studio 3.0, all in Kotlin. By Ivan Kušt.

Leave a rating/review
Save for later
Share

Since the beginning of Android, there was no out of the box solution for using custom fonts. Only a small set of preinstalled fonts on the device was available.

You had to be creative and write a lot of code for such a trivial thing.

Recently, Google introduced Custom and Downloadable fonts for Android 8.0. They’ve also provided support for earlier Android versions through Support Library version 26.

In this tutorial, you’ll get to know how to use them by creating a simple quiz app. In the process, you’ll learn:

  • How to add custom fonts in your app
  • How to define font families
  • How to add downloadable fonts from a provider
  • How to retrieve font information

Let there be fonts! :]

Note: This tutorial assumes you know the basics of Android development with Kotlin. If you are new to Kotlin check out our Kotlin introduction tutorial. If you are new to Android development, check out our Android Tutorials first.

History: Difficulties in the Past

Up until recently, to use a custom font on a View, you had to do several things:

  1. Put your font files in the assets folder
  2. Load the font from the asset file into a Typeface object
  3. Set that Typeface to your view using setTypeface()

The main disadvantage in this approach was that you couldn’t set the font in layout files – you had to do it in code:

val myTypeface = Typeface.createFromAsset(assets, "fonts/myFont.ttf")
myTextView.typeface = myTypeface

To remedy that you could extend your view classes and add a custom attribute for passing the font file from layout. That was a little bit better but there were still issues:

  • You had to extend every type of View you wanted to apply a custom font to
  • On some devices loading from assets could take a long time so you had to cache fonts in memory
  • In some cases things could get messy – for example if you had to change the font on Toolbar

Not to mention that it felt wrong extending a TextView just for setting a custom font.

Getting Started

Requirements

To work with custom fonts you’ll first have to install the latest Android Studio 3.x. This is important as some of the features are not supported on Android Studio 2.x – for example the font resource directory.

Install Android Studio by following the instructions in our Beginning Android development tutorial.

Your first task will be to switch to the latest support library. You can download the starter project here.

Open up Android Studio and import the starter project with File\Open. Select the location where you extracted the starter project and click Open on the dialog.

Once the project is open and synced, build and run the project.

You have a simple font quiz app. If you start the quiz you’ll get a series of 5 questions which ask you to guess the font of the text.

But wait – the text is always in the same (default) font! We’ll get to that shortly. First let’s add the latest support library.

Add the latest support library

Open build.gradle file in \app folder (in the Android project view you can find it under Gradle Scripts) and update the support library line in the dependencies { … } section:


implementation 'com.android.support:support-v4:27.0.2'


This will add the latest version of the Android support library that ports Custom and Downloadable fonts back to Android from API versions 14 up.

You also need to change your compileSdkVersion and targetSdkVersion to 27. Finally, change the other support library dependencies (i.e., appcompat and design) to version 27.0.2.

Once done, click Sync now on the gradle notification on top of editor window.

After gradle has synced up, build and run the app again to make sure everything is still working:

There is no visible change for now, but hold tight – we are ready to add some custom fonts!

Bundled fonts

Google introduced a new feature with Android 8 – font resources. Put font files into the res\font folder to bundle them in the .apk as resources. These fonts compile in the R file and are available in Android Studio the same way as string, drawable and color resources.

Note: Using font resources is possible in Android Studio 3.x and not in Android Studio 2.x.

The next thing you will do is add a custom .ttf font to the app. Download the OpenSans-regular font here.

Go back to Android Studio and make sure you select Android in Project navigator:

Click on the res folder, press ⌘N (or File\New) and select Directory.

A dialog to enter a new directory name will pop up. Name it font:

Now, right click on the new directory and click Reveal in Finder (macOS), Reveal in Explorer (Windows), or Show in Files (Linux). Move the downloaded OpenSans-Regular.ttf file to the fonts folder you’ve opened and rename it to opensans_regular.ttf. Only alphanumeric characters and underscore are valid in an android resource name.

Go back to Android Studio and open the res\layout\activity_main.xml file. Find AppCompatTextView with the id tvFontQuiz. Add the following property to it:

app:fontFamily="@font/opensans_regular"

The layout code for the text view should look like this now:


<android.support.v7.widget.AppCompatTextView
  android:id="@+id/tvMessage"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/quiz_message"
  android:textAlignment="center"
  app:fontFamily="@font/opensans_regular"
  app:layout_constraintBottom_toTopOf="@+id/startButton"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

Build and run your project.

You can see that the message is now in OpenSans font. Easy peasy!

Creating a font family

Another new capability is that you can create font families which contain a set of font files along with their style and weight details. To create a new font family you will actually create a new XML font resource. The benefit is that you can access it as a single unit instead of referencing individual font files for each style and weight as a separate resource.

You’ll now create a new font family. First, let’s get the bold version of OpenSans.

Repeat the same procedure from the last step and add new font file to the font folder of the project. Rename the file to opensans_bold.ttf.

The next thing you’ll do is create a font family resource.

Click on the res\font folder, press ⌘N (or File\New) and select Font resource file.

Type opensans under File name and click Ok.

Android studio will generate an empty font family resource:


<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">

</font-family>

Add two font files to the font family by using the <font> element. It has three attributes:

  • font: font file resource identifier
  • fontStyle: style to which the font file corresponds, can be normal or italic
  • fontWeight: text weight to use for the font

To add regular and italic font resource you’ll add two <font> elements:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android">
  <font
      android:fontStyle="normal"
      android:fontWeight="400"
      android:font="@font/opensans_regular" />
  <font
      android:fontStyle="italic"
      android:fontWeight="400"
      android:font="@font/opensans_bold" />
</font-family>

Note that to be backwards compatible to Android versions older than 8.0 you have to declare all font properties in the app namespace as well. This will use the custom font implementation from the support library. After adding them your resource file should look like this:

<?xml version="1.0" encoding="utf-8"?>
<font-family xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <font
        android:font="@font/opensans_regular"
        android:fontStyle="normal"
        android:fontWeight="400"
        app:fontFamily="@font/opensans_regular"
        app:fontStyle="normal"
        app:fontWeight="400" />
    <font
        android:font="@font/opensans_bold"
        android:fontStyle="italic"
        android:fontWeight="400"
        app:font="@font/opensans_bold"
        app:fontStyle="italic"
        app:fontWeight="400" />
</font-family>

Now go back to res/layout/activity_main.xml and change the app:fontFamily property on tvMessage to opensans:

<android.support.v7.widget.AppCompatTextView
  android:id="@+id/tvMessage"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/quiz_message"
  android:textAlignment="center"
  app:fontFamily="@font/opensans"
  app:layout_constraintBottom_toTopOf="@+id/startButton"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toTopOf="parent" />

Build and run your project.