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.

Advertisements

14 Comments »

  1. Great post, but isn’t it the other way around? I find that OTF is rendered correctly, and TTF looks bad on ICS.

    Comment by Alexex — March 11, 2012 @ 11:44 | Reply

    • I guess in the end it’s a matter of font. For the font I’ve used, only TTF was rendered correctly, OTF was missing the lower part for letters like g, y,q. Probably other forts will look better as OTF.

      Comment by alinberce — March 11, 2012 @ 11:54 | Reply

  2. Hi,
    what should i do to mix normal and bold in the same textview?
    i have two otf, for normal and for bold, if i use the normal, the bold part looks horrible, and whit the bold i cant get normal….
    the string is helloworld
    thanks!!!!

    Comment by David — March 16, 2012 @ 03:34 | Reply

  3. basically how to fix this
    http://groups.google.com/group/android-developers/browse_thread/thread/ee7d95ae1d619f7c?pli=1
    Thanks!!!!

    Comment by David — March 16, 2012 @ 03:44 | Reply

  4. very informative article.
    Can u please guide me how to use ttf files of language which are not supported by android, like HINDI ??????? ttf file—>> droidhindi.ttf

    Comment by Nitish — April 28, 2012 @ 13:32 | Reply

  5. […] have summed everything on a blog post here on my blog maybe it will help […]

    Pingback by Custom Fonts and Custom Textview on Android | PHP Developer Resource — May 29, 2012 @ 04:45 | Reply

  6. Hi! it’s a great post but i have a problem with the 3rd example, i made my own CustomTextView and extends from TextView and do exactly like you. But when i go to my xml throws an error like this “Typeface.createFromAsset() is not supported.” and i can’t do it in this way, but if i do the equivalent in my activity, it works:

    – If i do this in my CustomTextView, doesn’t work:
    public void setTypeface(Typeface tf, int style) {
    super.setTypeface(Typeface.createFromAsset(getContext().getAssets(), “MyriadPro-Semibold.ttf”),style);
    }
    – If i do in my activity, works fine:
    TextView txt = (TextView) findViewById(R.id.tvFirstName);
    Typeface font = Typeface.createFromAsset(getAssets(), “MyriadPro-Semibold.ttf”);
    txt.setTypeface(font);

    any idea?

    Comment by Itzehel — May 31, 2012 @ 02:47 | Reply

  7. Great Tutorial, ty!!! But how to set custom font to the ActionBar with Tabs (Fragments)? Seems that only TextView and Buttons ahve setTypeFace() method. :/

    Comment by Ralph Metel — June 20, 2012 @ 17:08 | Reply

  8. Awesome stuff…Hats off to you…I went thru various forums to create a custom font but it took ages to understand those while yours was pretty simple with great explanation for a beginner like me.

    Comment by Tejas — November 26, 2012 @ 18:21 | Reply

  9. Where is your FontsTutorial.src.zip? I tried to download it, but that site is full of adware and malware… I cant download it!

    Comment by ELY M. — December 11, 2012 @ 01:09 | Reply

  10. Great stuff! It is very helpful to customize font within app. keep blogging….

    Comment by A.Ramesh — February 4, 2013 @ 13:51 | Reply

  11. Great post, it’s perfect, thank you so much for this one.

    Comment by Clark Le — April 4, 2013 @ 18:20 | Reply

  12. Hi, what if i want to change font in my progressDialog?

    Comment by prashant — August 12, 2013 @ 03:45 | Reply

    • Lately for progress dialogs I am using FragmentDialog with my own layout. So basically I am making an xml layout in which I can have the views I want and then on my FragmantDialog’s onCreateView I inflate the layout and take care of the controls.

      Comment by alinberce — August 12, 2013 @ 09:02 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: