Android - Using Custom Font

252,951

Solution 1

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

Solution 2

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.

Solution 3

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>

Solution 4

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.

Solution 5

Provided that you placed the font in the right place and there is no error in the font file itself, your code should work like that, RATTLESNAKE.

However, it would be a lot easier if you could just define a font in your layout xml, like this:

<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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!-- This text view is styled with the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This uses my font in bold italic style" />

    <!-- This text view is styled here and overrides the app theme -->
    <com.innovattic.font.FontTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:flFont="anotherFont"
        android:textStyle="normal"
        android:text="This uses another font in normal style" />

    <!-- This text view is styled with a style and overrides the app theme -->
    <com.innovattic.font.FontTextView
        style="@style/StylishFont"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This also uses another font in normal style" />

</LinearLayout>

With the accompanying res/values/styles.xml:

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

    <!-- Application theme -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <item name="android:textViewStyle">@style/MyTextViewStyle</item>
    </style>

    <!-- Style to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextViewStyle" parent="@android:style/Widget.Holo.Light.TextView">
        <item name="android:textAppearance">@style/MyTextAppearance</item>
    </style>

    <!-- Text appearance to use for ALL text views (including FontTextView) -->
    <!-- Use a different parent if you don't want Holo Light -->
    <style name="MyTextAppearance" parent="@android:style/TextAppearance.Holo">
        <!-- Alternatively, reference this font with the name "aspergit" -->
        <!-- Note that only our own TextView's will use the font attribute -->
        <item name="flFont">someFont</item>
        <item name="android:textStyle">bold|italic</item>
    </style>

    <!-- Alternative style, maybe for some other widget -->
    <style name="StylishFont">
        <item name="flFont">anotherFont</item>
        <item name="android:textStyle">normal</item>
    </style>

</resources>

I created a couple of tools specifically for this purpose. Refer to this project from GitHub, or take a look at this blog post which explains the whole thing.

Share:
252,951

Related videos on Youtube

RATTLESNAKE
Author by

RATTLESNAKE

Web Developer

Updated on December 22, 2020

Comments

  • RATTLESNAKE
    RATTLESNAKE over 3 years

    I applied a custom font to a TextView, but it doesn't seems to change the typeface.

    Here is my code:

        Typeface myTypeface = Typeface.createFromAsset(getAssets(), "fonts/myFont.ttf");
        TextView myTextView = (TextView)findViewById(R.id.myTextView);
        myTextView.setTypeface(myTypeface);
    

    Can anyone please get me out of this issue?

    • yuttadhammo
      yuttadhammo over 12 years
      There's an error in your syntax, should be myTextView.setTypeface(myTypeface);
    • Snicolas
      Snicolas about 11 years
      This thread is similar to :stackoverflow.com/a/14558090/693752
    • Nilanchala Panigrahy
      Nilanchala Panigrahy about 11 years
    • Tofeeq Ahmad
      Tofeeq Ahmad almost 11 years
    • Diego Palomar
      Diego Palomar over 10 years
      Here you have an efficent way to change the font for the entire application: stackoverflow.com/questions/18847531/…
    • javaxian
      javaxian almost 10 years
      After trying most of the solutions described in this thread, I accidentally found Calligraphy - a library by Christopher Jenkins (github.com/chrisjenx/Calligraphy) 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.
  • Octavian Damiean
    Octavian Damiean over 13 years
    Edited my response with the solution now.
  • RATTLESNAKE
    RATTLESNAKE over 13 years
    Could u please send me some working demo project? I have tried both in assets/fonts/xyz.ttf and assets/xyz.ttf folder but it doesn't take that font. It displays only default font..
  • Octavian Damiean
    Octavian Damiean over 13 years
    Sure here is the link to the zipped up project. dl.dropbox.com/u/8288893/customFont.zip
  • Jameo
    Jameo about 11 years
    If you are following along with that tutorial, make sure you use the path Typeface.createFromAsset(getAssets(), "fonts/yourfont.ttf"); if you have put it in the fonts subdirectory
  • topher
    topher over 10 years
    don't include "assets/" in the filename (because createFromAsset function directly points inside assets directory)
  • Nublodeveloper
    Nublodeveloper over 9 years
    I updated my Nexus 7 to lollipop and this solution stopped working. Had been working up to KitKat. Any ideas?
  • Skynet
    Skynet over 8 years
    What does customAttrs refer to in my project?
  • CodyEngel
    CodyEngel about 8 years
    @Skynet it refers to the namespace defined in your root view which is xmlns:customAttrs="http://schemas.android.com/apk/res-auto". This automatically gets the attributes set for custom views. In this case you have an attribute called customFont defined in attrs.xml An easier way to understand is to look at xmlns:android="http://schemas.android.com/apk/res/android" which defines the namespace for your android attributes. So if you changed that to a then instead of android:text it'd be a:text.
  • Oliver Dixon
    Oliver Dixon over 7 years
    Please refer to my Answer, this isn't a full solution.
  • eRaisedToX
    eRaisedToX about 7 years
    what is the size of that library is an important question, because that's gonna affect the size of app.
  • albert c braun
    albert c braun almost 7 years
    Newer versions of Android Studio, along with Android "O", allow the "font" folder to be created inside the "res" folder. See updated answer by jeevan below.
  • Admin
    Admin almost 7 years
    Hi, I am using LG G4. I don't see any "asset" folder in my file explorer. Can somebody tell me where it is??
  • maXp
    maXp almost 7 years
    ony api > 26 ((
  • denvercoder9
    denvercoder9 over 6 years
  • Dipali Shah
    Dipali Shah over 6 years
    you should have appreciate my answer than! :)
  • Diaz diaz
    Diaz diaz almost 6 years
    WTH Bruv . this way must be in lower case . I was busting my head on this from 3 hours . THx
  • Code Wiget
    Code Wiget about 4 years
    This is missing a pretty big step #3... How do you do that?