Android Addicted Apps Creator

January 25, 2012

Using custom fonts in android. Bold, Italic, Regular… you name it!

Filed under: Android — alinberce @ 18:22
Tags: , , , , , , ,

As time has proven me, in Android many of the things I was used to make quite easy in .net, require a lot of manual coding. Using custom fonts does not make an exception… Everything depends on what you/your client wants to have in the app.

Brief intro regarding fonts.

First take a very good look at the font license. Of course, the best fonts, the handsome and good looking ones forbid free distribution. So in case you don’t want to have any legal issues, read carefully before using a certain font. Usually fonts are of two types: OTF stands for OpenType Font and TTF stands for TrueType Font (you can take a look at http://www.differencebetween.net/technology/difference-between-ttf-and-otf/ to see the difference between them). From what I have read around the web, they say that Android supports better TTF and is recommended that in case you want to use OTF to convert it. Personally I tried the both formats and all displayed well, so it’s up to you what type to use.

Setting things up. Put your coffee on your right…

The brief was very boring I know, but it was necessary. Now let’s settle our development environment. First, we need to use a free font. I have searched for an alternative to well known Myrian Pro from Adobe and recommendations went to Vegur. You can download it from: http://www.fontspace.com/arro/vegur . Please download the archive and take a look at it…

image

What in the name of God are those names you may say (as I did). That is the font indeed, but it is split into different files. So you’ve got Vegur-B 0.602 for Bold font, Vegur-R 0.602 for regular font and so on. When you create a project for android in Eclipse, you will see a folder called assets, make in assets new folder fonts and copy these two files in it and we’re done, fonts are added in our project. So simple, eh ?

image

How on earth do I use this font in my code ?

Let’s take a quick look at how a TextView is defined in an xml file.

<TextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="Regular TextView no typeface"
          android:textColor="#00FF00" />

<TextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="Regular TextView Monospace typeface"
          android:textColor="#00FF00"
          android:typeface="monospace" />

First TextView is plain and uses the default typeface. In the second TextView things are getting a bit complex as we have android:typeface attribute set to monospace. What does this mean ? The TextView will use Monospace font to display the text. Running the app will result in this:

image

I know what you are thinking… I’ll just replace monospace with my Vegur and we are done. Well, well, well… sorry to disappoint you, but there is no way we could use our custom font as a typeface straight from xml declaration. This is not cool. So all you code writing lovers, gather around as we need to dive into the wonderful world of custom controls.

Depending on your request there are several ways to do things, so we’ll take a good look and analyze/fix each one.

1.  I want a single TextView in my activity to use this font.

Maybe you have a logo text, or maybe you have some specific portion of text you need to make more obvious. In this case the solution is simple.

First add a new TextView in the main layout

<TextView
          android:id="@+id/txtOnlyOne"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="This TextView has our custom font"
          android:textColor="#00FF00" />

Go to main activity of the project, and within onCreate add this code:

Typeface tf = Typeface.createFromAsset(this.getAssets(), "fonts/Vegur-R 0.602.otf");
TextView tv = (TextView) findViewById(R.id.txtOnlyOne)
tv.setTypeface(tf);

image

Pretty simple and direct. We create the typeface in code and assign it to desired TextView. This may seem like a good solution in this case, but what if you face 20 TextViews ? It’s not so pleasant to find each one and assign the typeface to it. You could still try to do it this way, or you could go to next point…

2. I want the whoooooooooole activity to use this font.

Well, if setting it for a TextView was so simple…  setting it to all TextViews should be the same no ? The only thing that may give us trouble, is finding all the TextViews… so, why shouldn’t we look in all views and check? Take a look at this method:

private void overrideFonts(final Context context, final View v) {
      try {
        if (v instanceof ViewGroup) {
          ViewGroup vg = (ViewGroup) v;
         
			 for (int i = 0; i < vg.getChildCount(); i++) {
           	 View child = vg.getChildAt(i);
           	 overrideFonts(context, child);
         		 }

        } else if (v instanceof TextView ) {
          ((TextView) v).setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/Vegur-R 0.602.otf"));
        }

      } catch (Exception e) {
      }
    }

Simply add this line, on activity after setContentView and see the results:

  overrideFonts(this, findViewById(android.R.id.content));

image

Wow… all TextViews look the same way, using our custom font. Good job. We should be fine, let’s go home and celebrate. But hey, what if…

3. I want the first and third TextView with bold font

Ah, piece of cake, I’ll just add android:textStyle="bold" for them and everything should be fine. Run and see the results

image

Ups… what da’… no change, it still looks the same way, where is my bold setting gone?

And now we get back to intro where we say that font file is split into several files. We need somehow to make sure that our TextView considers the textStype attribute and acts according to it. The only way to achieve this goal, in a nice manner, is to create a custom TextView and handle our typeface change in it. To keep things short, as I see you are bored, here is our extended control:

public class MyTextView extends TextView {

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

     public MyTextView(Context context, AttributeSet attrs) {
          super(context, attrs);
      }

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


     public void setTypeface(Typeface tf, int style) {
           if (style == Typeface.BOLD) {
                super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/Vegur-B 0.602.otf")/*, -1*/);
            } else {
               super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "fonts/Vegur-R 0.602.otf")/*, -1*/);
            }
      }
 }

As you can see we intercept the setTypeface method, and depending of style value we assign our own custom typeface. To use it, simply add it in xml file

<com.alinberce.MyTextView
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="This MyTextView has our custom font"
         android:textColor="#00FF00" />

<com.alinberce.MyTextView
         android:id="@+id/txtOnlyOne"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="This MyTextView has our custom BOLD font"
         android:textStyle="bold"
         android:textColor="#00FF00" />

And finally we see it running and displaying the results as we wanted.

image

I personally use this as I don’t want to agglomerate my Activity code and allow me an easy way of changing the font for my entire app. You can simply put the "fonts/Vegur-B 0.602.otf" in a constant or a SharedPreference and when you change it, all you app will look different.

This post represents a resume of my questions on stackoverflow or answer found there. I just wanted to sum everything up and offer nuances of solutions based on everyone’s needs. I really hope you’ve understood it and will help you in the future. Please drop a comment if you liked it, or correct if I said something wrong.

You can find the source code of the article in this eclipse project : http://ifile.it/p0ovny3/FontsTutorial.src.zip

image

LATER EDIT: As time has proven me once again, Android is full of surprises. Using this font on Froyo/Gingerbread worked superb but on ICS… was rendered badly. The fix was quite easy: convert the OTF file to TTF using a free online font converter. Using the same font, but with TTF extension made the app look the same on all versions of Android. So kids, remember… Hate OTF, love TTF.