Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android - Using Custom Font

On Mobiletuts+ there is very good tutorial on Text formatting for Android. Quick Tip: Customize Android Fonts

EDIT: Tested it myself now. Here is the solution. You can use a subfolder called fonts but it must go in the assets folder not the res folder. So

assets/fonts

Also make sure that the font ending I mean the ending of the font file itself is all lower case. In other words it should not be myFont.TTF but myfont.ttf this way must be in lower case


After trying most of the solutions described in this thread, I accidentally found Calligraphy (https://github.com/chrisjenx/Calligraphy) - a library by Christopher Jenkins that lets you easily add custom fonts to your app. The advantages of his lib comparing to approaches suggested here are:

  1. you don't have to introduce your own overriden TextView component, you use the built-in TextView
  2. you can easily include the library using gradle
  3. The library doesn't limit your choice of fonts; you just add your preferred ones to the assets dir
  4. you not only get custom text views — all the other text-based Android compontents will also be displayed using your custom font.

I know there are good answers already, but here's a fully working implementation.

Here's the custom text view:

package com.mycompany.myapp.widget;

/**
 * Text view with a custom font.
 * <p/>
 * In the XML, use something like {@code customAttrs:customFont="roboto-thin"}. The list of fonts
 * that are currently supported are defined in the enum {@link CustomFont}. Remember to also add
 * {@code xmlns:customAttrs="http://schemas.android.com/apk/res-auto"} in the header.
 */
public class CustomFontTextView extends TextView {

    private static final String sScheme =
            "http://schemas.android.com/apk/res-auto";
    private static final String sAttribute = "customFont";

    static enum CustomFont {
        ROBOTO_THIN("fonts/Roboto-Thin.ttf"),
        ROBOTO_LIGHT("fonts/Roboto-Light.ttf");

        private final String fileName;

        CustomFont(String fileName) {
            this.fileName = fileName;
        }

        static CustomFont fromString(String fontName) {
            return CustomFont.valueOf(fontName.toUpperCase(Locale.US));
        }

        public Typeface asTypeface(Context context) {
            return Typeface.createFromAsset(context.getAssets(), fileName);
        }
    }

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

        if (isInEditMode()) {
            return;
        } else {
            final String fontName = attrs.getAttributeValue(sScheme, sAttribute);

            if (fontName == null) {
                throw new IllegalArgumentException("You must provide \"" + sAttribute + "\" for your text view");
            } else {
                final Typeface customTypeface = CustomFont.fromString(fontName).asTypeface(context);
                setTypeface(customTypeface);
            }
        }
    }
}

Here's the custom attributes. This should go to your res/attrs.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="CustomFontTextView">
        <attr name="customFont" format="string"/>
    </declare-styleable>
</resources>

And here's how you use it. I'll use a relative layout to wrap it and show the customAttr declaration, but it could obviously be whatever layout you already have.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:customAttrs="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.mycompany.myapp.widget.CustomFontTextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="foobar"
         customAttrs:customFont="roboto_thin" />

</RelativeLayout>

I've successfully used this before. The only difference between our implementations is that I wasn't using a subfolder in assets. Not sure if that will change anything, though.