Custom Fonts in Android

5 minutes read

Table of Content

Introduction

Android does not have a standard way of adding custom fonts using XML. We can add them programmatically at run time but that is not a flexible approach. Using custom attributes , we can  setup the custom fonts in android using XML.

I’ve taken example of Roboto Font  for this demo.  This font needs API level >11 to be used directly. We  will use it as a custom font.

Steps

Copy Fonts to assets folder

Create a folder in the root of your project called assets/fonts/ and paste the Roboto TTF font files available from the android typography website.

Define Custom attributes

Define the custom attributes that are going to be used in /values/attrs.xml. The name attribute points to the custom widget that will use that attribute to set the common font.


<declare-styleable name="RobotoTextView">

    <attr name="typeface"/>

</declare-styleable>

<attr name="typeface" format="enum">

    <enum name="roboto_thin" value="0"/>

    <enum name="roboto_thin_italic" value="1"/>

    <enum name="roboto_light" value="2"/>

    <enum name="roboto_light_italic" value="3"/>

    <enum name="roboto_regular" value="4"/>

    <enum name="roboto_italic" value="5"/>

    <enum name="roboto_medium" value="6"/>

    <enum name="roboto_medium_italic" value="7"/>

    <enum name="roboto_bold" value="8"/>

    <enum name="roboto_bold_italic" value="9"/>

    <enum name="roboto_black" value="10"/>

    <enum name="roboto_black_italic" value="11"/>

    <enum name="roboto_condensed" value="12"/>

    <enum name="roboto_condensed_italic" value="13"/>

    <enum name="roboto_condensed_bold" value="14"/>

    <enum name="roboto_condensed_bold_italic" value="15"/>

</attr>
</resources>

Define Custom TextView

We will define a custom text view to use the custom fonts.


package com.sanjaymeena.customfont.widgets;

import com.sanjaymeena.customfont.R;

import com.sanjaymeena.customfont.R.styleable;



import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Typeface;

import android.util.AttributeSet;

import android.util.SparseArray;

import android.widget.TextView;



public class RobotoTextView extends TextView {



/*

 * Permissible values ​​for the "typeface" attribute.

 */

private final static int ROBOTO_THIN = 0;

private final static int ROBOTO_THIN_ITALIC = 1;

private final static int ROBOTO_LIGHT = 2;

private final static int ROBOTO_LIGHT_ITALIC = 3;

private final static int ROBOTO_REGULAR = 4;

private final static int ROBOTO_ITALIC = 5;

private final static int ROBOTO_MEDIUM = 6;

private final static int ROBOTO_MEDIUM_ITALIC = 7;

private final static int ROBOTO_BOLD = 8;

private final static int ROBOTO_BOLD_ITALIC = 9;

private final static int ROBOTO_BLACK = 10;

private final static int ROBOTO_BLACK_ITALIC = 11;

private final static int ROBOTO_CONDENSED = 12;

private final static int ROBOTO_CONDENSED_ITALIC = 13;

private final static int ROBOTO_CONDENSED_BOLD = 14;

private final static int ROBOTO_CONDENSED_BOLD_ITALIC = 15;

/**

 * List of created typefaces for later reused.

 */

private final static SparseArray<Typeface> mTypefaces = new SparseArray<Typeface>(16);



/**

 * Simple constructor to use when creating a view from code.

 *

 * @param context The Context the view is running in, through which it can

 *                access the current theme, resources, etc.

 */

public RobotoTextView(Context context) {

    super(context);

}



/**

 * Constructor that is called when inflating a view from XML. This is called

 * when a view is being constructed from an XML file, supplying attributes

 * that were specified in the XML file. This version uses a default style of

 * 0, so the only attribute values applied are those in the Context's Theme

 * and the given AttributeSet.

 * <p/>

 * <p/>

 * The method onFinishInflate() will be called after all children have been

 * added.

 *

 * @param context The Context the view is running in, through which it can

 *                access the current theme, resources, etc.

 * @param attrs   The attributes of the XML tag that is inflating the view.

 * @see #RobotoTextView(Context, AttributeSet, int)

 */

public RobotoTextView(Context context, AttributeSet attrs) {

    super(context, attrs);

    parseAttributes(context, attrs);

}



/**

 * Perform inflation from XML and apply a class-specific base style. This

 * constructor of View allows subclasses to use their own base style when

 * they are inflating.

 *

 * @param context  The Context the view is running in, through which it can

 *                 access the current theme, resources, etc.

 * @param attrs    The attributes of the XML tag that is inflating the view.

 * @param defStyle The default style to apply to this view. If 0, no style

 *                 will be applied (beyond what is included in the theme). This may

 *                 either be an attribute resource, whose value will be retrieved

 *                 from the current theme, or an explicit style resource.

 * @see #RobotoTextView(Context, AttributeSet)

 */

public RobotoTextView(Context context, AttributeSet attrs, int defStyle) {

    super(context, attrs, defStyle);

    parseAttributes(context, attrs);

}



/**

 * Parse the attributes.

 *

 * @param context The Context the view is running in, through which it can access the current theme, resources, etc.

 * @param attrs   The attributes of the XML tag that is inflating the view.

 */

private void parseAttributes(Context context, AttributeSet attrs) {

    TypedArray values = context.obtainStyledAttributes(attrs, R.styleable.RobotoTextView);



    int typefaceValue = values.getInt(R.styleable.RobotoTextView_typeface, 0);

    values.recycle();



    setTypeface(obtaintTypeface(context, typefaceValue));

}



/**

 * Obtain typeface.

 *

 * @param context       The Context the view is running in, through which it can

 *                      access the current theme, resources, etc.

 * @param typefaceValue values ​​for the "typeface" attribute

 * @return Roboto {@link Typeface}

 * @throws IllegalArgumentException if unknown `typeface` attribute value.

 */

private Typeface obtaintTypeface(Context context, int typefaceValue) throws IllegalArgumentException {

    Typeface typeface = mTypefaces.get(typefaceValue);

    if (typeface == null) {

        typeface = createTypeface(context, typefaceValue);

        mTypefaces.put(typefaceValue, typeface);

    }

    return typeface;

}



/**

 * Create typeface from assets.

 *

 * @param context       The Context the view is running in, through which it can

 *                      access the current theme, resources, etc.

 * @param typefaceValue values ​​for the "typeface" attribute

 * @return Roboto {@link Typeface}

 * @throws IllegalArgumentException if unknown `typeface` attribute value.

 */

private Typeface createTypeface(Context context, int typefaceValue) throws IllegalArgumentException {

    Typeface typeface;

    switch (typefaceValue) {

        case ROBOTO_THIN:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Thin.ttf");

            break;

        case ROBOTO_THIN_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf");

            break;

        case ROBOTO_LIGHT:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");

            break;

        case ROBOTO_LIGHT_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-LightItalic.ttf");

            break;

        case ROBOTO_REGULAR:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Regular.ttf");

            break;

        case ROBOTO_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");

            break;

        case ROBOTO_MEDIUM:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf");

            break;

        case ROBOTO_MEDIUM_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-MediumItalic.ttf");

            break;

        case ROBOTO_BOLD:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");

            break;

        case ROBOTO_BOLD_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldItalic.ttf");

            break;

        case ROBOTO_BLACK:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Black.ttf");

            break;

        case ROBOTO_BLACK_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BlackItalic.ttf");

            break;

        case ROBOTO_CONDENSED:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Condensed.ttf");

            break;

        case ROBOTO_CONDENSED_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-CondensedItalic.ttf");

            break;

        case ROBOTO_CONDENSED_BOLD:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensed.ttf");

            break;

        case ROBOTO_CONDENSED_BOLD_ITALIC:

            typeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-BoldCondensedItalic.ttf");

            break;

        default:

            throw new IllegalArgumentException("Unknown `typeface` attribute value " + typefaceValue);

    }

    return typeface;

}



}

Use custom font in layout file

Now we can use the custom fonts through the layout files. We need to reference the namespace  in our layout file:

xmlns:app=”https://schemas.android.com/apk/res/com.sanjaymeena.customfont”

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"

    xmlns:tools="https://schemas.android.com/tools"

    xmlns:app="https://schemas.android.com/apk/res/com.sanjaymeena.customfont"

    android:id="@+id/ideapager_scrollview"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    tools:context=".MainActivity" >



    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="0dip"

        android:orientation="vertical" >



        <TextView

            android:id="@+id/default1"

            android:layout_width="match_parent"

            android:layout_height="0dp"

            android:layout_gravity="center_vertical"

            android:layout_marginLeft="10dp"

            android:layout_marginRight="10dp"

            android:layout_weight="1"

            android:orientation="vertical"

            android:paddingBottom="10dp"

            android:paddingLeft="10dp"

            android:paddingRight="10dp"

            android:text="@string/def"

            android:textSize="20sp" />



        <com.sanjaymeena.customfont.widgets.RobotoTextView

            android:id="@+id/id1"

            android:layout_width="match_parent"

            android:layout_height="0dp"

            android:layout_gravity="center_vertical"

            android:layout_marginLeft="10dp"

            android:layout_marginRight="10dp"

            android:layout_weight="1"

            android:orientation="vertical"

            android:paddingBottom="10dp"

            android:paddingLeft="10dp"

            android:paddingRight="10dp"

            android:text="@string/customfont1"

            android:textSize="20sp"

            app:typeface="roboto_bold" />



        <com.sanjaymeena.customfont.widgets.RobotoTextView

            android:id="@+id/id2"

            android:layout_width="match_parent"

            android:layout_height="0dp"

            android:layout_gravity="center_vertical"

            android:layout_marginLeft="10dp"

            android:layout_marginRight="10dp"

            android:layout_weight="1"

            android:orientation="vertical"

            android:paddingBottom="10dp"

            android:paddingLeft="10dp"

            android:paddingRight="10dp"

            android:text="@string/customfont2"

            android:textSize="20sp"

            app:typeface="roboto_regular" />



        <com.sanjaymeena.customfont.widgets.RobotoTextView

            android:id="@+id/id4"

            android:layout_width="match_parent"

            android:layout_height="0dp"

            android:layout_gravity="center_vertical"

            android:layout_marginLeft="10dp"

            android:layout_marginRight="10dp"

            android:layout_weight="1"

            android:orientation="vertical"

            android:paddingBottom="10dp"

            android:paddingLeft="10dp"

            android:paddingRight="10dp"

            android:text="@string/customfont3"

            android:textSize="20sp"

            app:typeface="roboto_thin" />

    </LinearLayout>
</ScrollView>

Get the source code here

Updated:

Leave a Comment