Android Custom Fonts Tutorial

Filed Under: Android

In this tutorial, we’ll explain how to set up android custom fonts in TextViews and Buttons in our application.

Android Custom Fonts

Android SDK comes with a set of standard fonts that can be styled by using a few XML attributes. Let’s look at them.

  • android:fontFamily : This is used to change the default fonts of the application. We can choose the font from among the following types.

    android font family types, android custom fonts

    The default fontFamily is sans-serif.
    android:fontFamily requires minimum API level as 16.

  • android:typeface : This XML attribute won’t have any effect if the fontFamily is already used(Unless the API level is less than 15, in which case the fontFamily attribute would be ignored). normal or sans is the default type of this attribute. Following are the values acceptable.
    android typeface xml types, android custom fonts
  • android:textStyle : This attribute takes in values : bold, italic and normal either individually or combined such as android:textStyle=”bold|italic”.

Let’s club android:fontFamily and android:textStyle and display the different variants of a TextView.

The styles.xml which contains the different style variants is given below.


<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>


    <style name="Regular">
        <item name="android:fontFamily">sans-serif</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif</item>
    </style>

    <style name="Italic">
    <item name="android:fontFamily">sans-serif</item>
    <item name="android:textStyle">italic</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif</item>
    </style>


    <style name="Bold">
        <item name="android:fontFamily">sans-serif</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif</item>
    </style>

    <style name="BoldItalic">
        <item name="android:fontFamily">sans-serif</item>
        <item name="android:textStyle">bold|italic</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif</item>
    </style>

    <style name="RegularCondensed">
        <item name="android:fontFamily">sans-serif-condensed</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif-condensed</item>
    </style>

    <style name="ItalicCondensed">
        <item name="android:fontFamily">sans-serif-condensed</item>
        <item name="android:textStyle">italic</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif-condensed</item>
    </style>


    <style name="BoldCondensed">
        <item name="android:fontFamily">sans-serif-condensed</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">sans-serif-condensed</item>
    </style>

    <style name="Casual">
        <item name="android:fontFamily">casual</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">Casual</item>
    </style>

    <style name="Cursive">
        <item name="android:fontFamily">cursive</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">Cursive</item>
    </style>

    <style name="RegularMono">
        <item name="android:fontFamily">monospace</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">mono space</item>
    </style>

    <style name="ItalicMono">
        <item name="android:fontFamily">monospace</item>
        <item name="android:textStyle">italic</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">monospace</item>
    </style>

    <style name="BoldMono">
        <item name="android:fontFamily">monospace</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">monospace</item>
    </style>

    <style name="RegularMonoSerif">
        <item name="android:fontFamily">serif-monospace</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">serif-monospace</item>
    </style>

    <style name="ItalicMonoSerif">
        <item name="android:fontFamily">serif-monospace</item>
        <item name="android:textStyle">italic</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">serif-monospace</item>
    </style>

    <style name="BoldMonoSerif">
        <item name="android:fontFamily">serif-monospace</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textSize">28sp</item>
        <item name="android:text">serif-monospace</item>
    </style>



</resources>

The activity_main.xml is given below.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.journaldev.customfonts.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Regular"
         />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Italic"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Bold" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/RegularCondensed" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/ItalicCondensed"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/BoldCondensed"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Casual"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Cursive"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/RegularMono"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/ItalicMono"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/BoldMono"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/RegularMonoSerif" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/ItalicMonoSerif"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/BoldMonoSerif"
        />

</LinearLayout>

android standard font variants

To set custom fonts on a TextView/Button/EditText object, the Typeface property is used.
The Typeface class specifies the typeface and intrinsic style of a font.
To set a typeface over a TextView we invoke the method setTypeface().
Following are the Typeface constants that can be used.

  • BOLD
  • BOLD_ITALIC
  • ITALIC
  • NORMAL

To set custom fonts on our Views, we first need to import the font files into our project.
Font files generally come up in two types .ttf (True Type Font) and .otf (Open Type Font).

Android Custom Fonts Project Structure

android custom fonts project
In the above image a new folder assets has been added under the main directory.

Android Custom Fonts Code

We’ve created another layout namely activity_custom_fonts.xml for setting custom fonts on our Views.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.journaldev.customfonts.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Bold"
        android:textSize="28sp"
        android:id="@+id/ambleBold"
         />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Light"
        android:textSize="28sp"
        android:id="@+id/ambleLight"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Regular"
        android:textSize="28sp"
        android:id="@+id/ambleRegular" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OpenSans Regular"
        android:textSize="28sp"
        android:id="@+id/opRegular" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OpenSans-Italic"
        android:id="@+id/opItalic"
        android:textSize="28sp"
        />

    <Button android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="Pacifico"
        android:id="@+id/pacifico"/>




</LinearLayout>

We’re setting our custom fonts in the java code. The MainActivity.java is given below


public class MainActivity extends AppCompatActivity {


    TextView ambleBold, ambleLight, ambleRegular, openSansItalic, openSansRegular;
    Button btn;

    private String A_BOLD= "Amble-Bold.ttf";
    private String A_LIGHT="Amble-Light.ttf";
    private String A_REGULAR= "Amble-Regular.ttf";
    private String O_ITALIC= "OpenSans-Italic.ttf";
    private String O_REGULAR="OpenSans-Regular.ttf";
    private String P_REGULAR="Pacifico.ttf";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_fonts);

        ambleBold=(TextView)findViewById(R.id.ambleBold);
        ambleLight=(TextView)findViewById(R.id.ambleLight);
        ambleRegular=(TextView)findViewById(R.id.ambleRegular);
        openSansRegular=(TextView)findViewById(R.id.opRegular);
        openSansItalic=(TextView)findViewById(R.id.opItalic);
        btn=(Button)findViewById(R.id.pacifico);

        ambleBold.setTypeface(Typeface.createFromAsset(getAssets(), A_BOLD));
        ambleLight.setTypeface(Typeface.createFromAsset(getAssets(), A_LIGHT));
        ambleRegular.setTypeface(Typeface.createFromAsset(getAssets(), A_REGULAR));
        openSansRegular.setTypeface(Typeface.createFromAsset(getAssets(), O_REGULAR));
        openSansItalic.setTypeface(Typeface.createFromAsset(getAssets(), O_ITALIC));
        btn.setTypeface(Typeface.createFromAsset(getAssets(), P_REGULAR));


    }
}

In the above code we’re calling createFromAsset() method on the Typeface class to create a new instance of the Typeface. An instance of the application’s AssetManager is called by passing getAssets() as the first parameter. The custom font asset file path is passed as a string in the second parameter. Since we’ve placed the font files in the root of assets directory, passing the font filenames would suffice.

Note: Setting external fonts using android:typeface doesn’t work

We end up with the following output when the application is run.

android custom fonts output

Isn’t it a time consuming and redundant task to set the typeface individually for each of the views?
We need a better alternative. Our answer lies in Custom Views. In the next section, we’ll be creating a Custom TextView class and define custom XML attributes to set the external fonts in the XML layout itself.

Our Updated Project Structure is given below
android custom fonts project structure

Before we implement our CustomTextView.java, let’s look into the TypeFactory.java class as shown below.


public class TypeFactory {

    private String A_BOLD= "Amble-Bold.ttf";
    private String A_LIGHT="Amble-Light.ttf";
    private String A_REGULAR= "Amble-Regular.ttf";
    private String O_ITALIC= "OpenSans-Italic.ttf";
    private String O_REGULAR="OpenSans-Regular.ttf";

    Typeface ambleBold;
    Typeface ambleLight;
    Typeface ambleRegular;
    Typeface openSansItalic;
    Typeface openSansRegular;

    public TypeFactory(Context context){
        ambleBold = Typeface.createFromAsset(context.getAssets(),A_BOLD);
        ambleLight = Typeface.createFromAsset(context.getAssets(),A_LIGHT);
        ambleRegular = Typeface.createFromAsset(context.getAssets(),A_REGULAR);
        openSansItalic = Typeface.createFromAsset(context.getAssets(),O_ITALIC);
        openSansRegular = Typeface.createFromAsset(context.getAssets(),O_REGULAR);
    }

}

The above code essentially creates a custom typeface font for each of the font files. We can now use the class variables in our CustomTextView to set the font accordingly.

The CustomTextView.java class is given below.


public class CustomTextView extends TextView {

    private int typefaceType;
    private TypeFactory mFontFactory;

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        applyCustomFont(context, attrs);
    }

    public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        applyCustomFont(context, attrs);
    }

    public CustomTextView(Context context) {
        super(context);
    }

    private void applyCustomFont(Context context, AttributeSet attrs) {


        TypedArray array = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CustomTextView,
                0, 0);
        try {
            typefaceType = array.getInteger(R.styleable.CustomTextView_font_name, 0);
        } finally {
            array.recycle();
        }
        if (!isInEditMode()) {
            setTypeface(getTypeFace(typefaceType));
        }

    }

    public Typeface getTypeFace(int type) {
        if (mFontFactory == null)
            mFontFactory = new TypeFactory(getContext());

        switch (type) {
            case Constants.A_BOLD:
                return mFontFactory.ambleBold;

            case Constants.A_LIGHT:
                return mFontFactory.ambleLight;

            case Constants.A_REGULAR:
                return mFontFactory.ambleRegular;

            case Constants.O_LIGHT:
                return mFontFactory.openSansItalic;

            case Constants.O_REGULAR:
                return mFontFactory.openSansRegular;

            default:
                return mFontFactory.ambleBold;
        }
    }

    public interface Constants {
        int A_BOLD = 1,
                A_LIGHT = 2,
                A_REGULAR = 3,
                O_LIGHT = 4,
        O_REGULAR=5;
    }


}

R.styleable.CustomTextView is defined inside the attrs.xml file as shown below.


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

    <declare-styleable name="CustomTextView">
        <attr name="font_name">
            <enum value="1" name="ambleBold"/>
            <enum value="2" name="ambleLight"/>
            <enum value="3" name="ambleRegular"/>
            <enum value="4" name="openSansItalic"/>
            <enum value="5" name="openSansRegular"/>
        </attr>
    </declare-styleable>

</resources>

The attribute font_name is the custom attribute we’ll be using in the XML layout.

Our updated activity_custom_fonts.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.journaldev.customfonts.MainActivity">

    <com.journaldev.customfonts.CustomTextView
        app:font_name="ambleBold"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Bold"
        android:textSize="28sp"
        android:id="@+id/ambleBold"
         />

    <com.journaldev.customfonts.CustomTextView
        app:font_name="ambleLight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Light"
        android:textSize="28sp"
        android:id="@+id/ambleLight"
        />

    <com.journaldev.customfonts.CustomTextView
        app:font_name="ambleRegular"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Amble Regular"
        android:textSize="28sp"
        android:id="@+id/ambleRegular" />

    <com.journaldev.customfonts.CustomTextView
        app:font_name="openSansRegular"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OpenSans Regular"
        android:textSize="28sp"
        android:id="@+id/opRegular" />

    <com.journaldev.customfonts.CustomTextView
        app:font_name="openSansItalic"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="OpenSans-Italic"
        android:id="@+id/opItalic"
        android:textSize="28sp"
        />

    <Button android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:text="Pacifico"
        android:id="@+id/pacifico"/>

</LinearLayout>

The MainActivity.java code now would just require setting the Button typeface.

Note: A CustomButton Custom View can be created in a similar way. Try that out!

This brings an end to this tutorial. You can download the Android CustomFonts Tutorial from the below link.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages