The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Fonts and Text

Inevitably, you’ll get the question “hey, can we change this font?” when doing application development. The answer depends on what fonts come with the platform, whether you can add other fonts, and how to apply them to the widget or whatever needs the font change.

Android is no different. It comes with some fonts plus a means for adding new fonts. Though, as with any new environment, there are a few idiosyncrasies to deal with.

Prerequisites

Understanding this chapter requires that you have read the core chapters, particularly the one on files.

Love The One You’re With

Android natively knows three fonts, by the shorthand names of “sans”, “serif”, and “monospace”. For Android 1.x, 2.x, and 3.x, these fonts are actually the Droid series of fonts, created for the Open Handset Alliance by Ascender. A new font set, Roboto, is used in Android 4.x and beyond, though the look of the font changed somewhat in Android 5.0.

For those fonts, you can just reference them in your layout XML, if you choose, such as the following layout from the Fonts/FontSampler sample project:

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:stretchColumns="1">

  <TableRow>

    <TextView
      android:layout_marginRight="4dip"
      android:text="@string/label_sans"
      android:textSize="20sp" />

    <TextView
      android:id="@+id/sans"
      android:text="@string/hello_world"
      android:textSize="20sp"
      android:typeface="sans" />
  </TableRow>

  <TableRow>

    <TextView
      android:layout_marginRight="4dip"
      android:text="@string/label_serif"
      android:textSize="20sp" />

    <TextView
      android:id="@+id/serif"
      android:text="@string/hello_world"
      android:textSize="20sp"
      android:typeface="serif" />
  </TableRow>

  <TableRow>

    <TextView
      android:layout_marginRight="4dip"
      android:text="@string/label_monospace"
      android:textSize="20sp" />

    <TextView
      android:id="@+id/monospace"
      android:text="@string/hello_world"
      android:textSize="20sp"
      android:typeface="monospace" />
  </TableRow>

  <TableRow>

    <TextView
      android:layout_marginRight="4dip"
      android:text="@string/label_custom"
      android:textSize="20sp" />

    <TextView
      android:id="@+id/custom"
      android:text="@string/hello_world"
      android:textSize="20sp" />
  </TableRow>

  <TableRow android:id="@+id/filerow">

    <TextView
      android:layout_marginRight="4dip"
      android:text="@string/label_custom_from_file"
      android:textSize="20sp" />

    <TextView
      android:id="@+id/file"
      android:text="@string/hello_world"
      android:textSize="20sp" />
  </TableRow>
</TableLayout>

This layout builds a table showing short samples of five fonts. Notice how the first three have the android:typeface attribute, whose value is one of the three built-in font faces (e.g., “sans”).

The three built-in fonts are very nice. However, it may be that a designer, or a manager, or a customer wants a different font than one of those three. Or perhaps you want to use a font for specialized purposes, such as an image font instead of a series of PNG graphics.

The easiest way to accomplish this is to package the desired font(s) with your application. To do this, simply create an assets/ folder in the project root, and put your TrueType (TTF) fonts in the assets. You might, for example, create assets/fonts/ and put your TTF files in there. Note that Android has some support for OpenType (OTF) fonts, as well.

Then, you need to tell your widgets to use that font. Unfortunately, you can no longer use layout XML for this, since the XML does not know about any fonts you may have tucked away as an application asset. Instead, you need to make the change in Java code:

package com.commonsware.android.fonts;

import android.app.Activity;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.TextView;
import java.io.File;

public class FontSampler extends Activity {
  @Override
  public void onCreate(Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.main);
    
    TextView tv=(TextView)findViewById(R.id.custom);
    Typeface face=
      Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf");
    
    tv.setTypeface(face);
    
    File font=
      new File(Environment.getExternalStorageDirectory(), "MgOpenCosmeticaBold.ttf");
    
    if (font.exists()) {
      tv=(TextView)findViewById(R.id.file);
      face=Typeface.createFromFile(font);
      
      tv.setTypeface(face);
    }
    else {
      findViewById(R.id.filerow).setVisibility(View.GONE);
    }
  }
}

Here we grab the TextView for our “custom” sample, then create a Typeface object via the static createFromAsset() builder method. This takes the application’s AssetManager (from getAssets()) and a path within your assets/ directory to the font you want.

Then, it is just a matter of telling the TextView to setTypeface(), providing the Typeface you just created. In this case, we are using the Handmade Typewriter font.

You can also load a font out of a local file and use it. The benefit is that you can customize your fonts after your application has been distributed. On the other hand, you have to somehow arrange to get the font onto the device. But just as you can get a Typeface via createFromAsset(), you can get a Typeface via createFromFile(). In our FontSampler, we look in the root of “external storage” (typically the SD card) for the MgOpenCosmeticaBold TrueType font file, and if it is found, we use it for the fifth row of the table. Otherwise, we hide that row.

The results?

The FontSampler application
Figure 551: The FontSampler application

Note that Android does not seem to like all TrueType fonts. When Android dislikes a custom font, rather than raise an Exception, it seems to substitute Droid Sans (“sans”) quietly. So, if you try to use a different font and it does not seem to be working, it may be that the font in question is incompatible with Android, for whatever reason.

Yeah, But Do We Really Have To Do This in Java?

The preview of this section is unavailable right now, but if you leave your name and number at the sound of the tone, it might get back to you (BEEEEEEEEEEEEP!).

Here a Glyph, There a Glyph

The preview of this section took that left turn at Albuquerque.

Auto-Sizing TextView

The preview of this section is in an invisible, microscopic font.

Justified Text

The preview of this section was lost in the sofa cushions.