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.

May 14, 2009

Custom Combo Box with colors and text – Part II

Filed under: Windows forms — alinberce @ 17:39
Tags: ,

(Warning: for bored people, who are too tired to read all this bla bla, just go to the end of the post for the video)

         Yesterday we did pretty cool things with the ComboBox control. Today we’ll enhance it a little bit more. The previous solution works great if you don’t need many ComboBoxes. But if you do, than it would be uncomfortable to write DrawItem methods for each one. To get rid of this issue, we’ll create a custom ComboBox which will do the job for us. Sounds nice ?

Add a new class to the project and name it CboColors.cs. This will contain a custom ComboBox control with it’s overridden methods, in order to spare us from doing the same things over and over again.

Here is the code:

using System.Drawing;
using System.Windows.Forms;

namespace qPlanner.UserControls
{
    public partial class cboColored : ComboBox
    {
        protected override void OnCreateControl()
        {
            base.OnCreateControl();

            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.DropDownStyle = ComboBoxStyle.DropDownList;
            this.MaxDropDownItems = 11;
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            base.OnDrawItem(e);

            e.DrawBackground();
            if (e.Index >= 0)
            {
                object current = this.Items[e.Index];
                object currentValue = current.GetType().GetProperty(this.ValueMember).GetGetMethod().Invoke(current, null);
                object currentDisplay = current.GetType().GetProperty(this.DisplayMember).GetValue(current, null);
                Color clr = currentValue is Color ? (Color)currentValue : Color.Black;
                using (Brush brush = new SolidBrush(clr))
                {
                    e.Graphics.FillRectangle(brush, e.Bounds.X + 1, e.Bounds.Y + 1, 13, 13);
                }
                using (Brush brush = new SolidBrush(e.ForeColor))
                {
                    e.Graphics.DrawString(currentDisplay.ToString(), e.Font, brush, e.Bounds.Left + 16, e.Bounds.Top);
                }
                e.DrawFocusRectangle();
            }

        }
    }
}

The changes from the previous part are not very obvious, but they make the difference. As you can see, now I won’t take the information about Color and Name from the ComboBox’s DataSource but from the current drawn item itself.

Build the solution. Now get back to the Form1 in Design mode. In the ToolBox there should be a brand new item named cboColored.

image

Drag this item into the form and rename it to cboColored. The only thing that remains to do is give this custom ComboBox a DataSource.

private void GetPriorityList()
        {
            lstPriority = PriorityCollections.GetPriorities();
            cboPriority.DataSource = lstPriority;
            cboPriority.ValueMember = "Color";
            cboPriority.DisplayMember = "Name";
          //added for the custom combo
            cboColored.DataSource = lstPriority;
            cboColored.ValueMember = "Color";
            cboColored.DisplayMember = "Name";

        }       

Run the project and it should look like this:

image

Wow. It works. It’s that simple, just add a DataSource, ValueMember and DisplayMember and you’re done. Happy coding.

May 10, 2009

Combo Box with colors and text – Part I

Filed under: Windows forms — alinberce @ 17:46
Tags: ,

First things, first: A BIG BIG THANK YOU, for my friend Claudiu which always gives me the right solution when I’m stuck and has the nonhuman patience to teach me . Respect.

I’ve seen in some applications pretty nice combo boxes that contained beside the text some graphics too. So, I thought, why not make one myself? It can’t be that hard… no? Well, not very hard but, very interesting. In order to achieve this, I will take a simple example from the qPlanner application: each task has a certain priority, let’s say “High”, “Medium”, “Low”. Each priority type has a specific color: Red, Orange, Green. The combo box control will have to be able to display a small square with the color and the text of the priority.

Get ready, take a big breath, and let’s try to do it together.

First of all let’s create a new project, of type Window forms application. I will name it ColoredCombo. Open Form1 and add to it a ComboBox, name it cboPriority and set it’s DropDownStyle to DropDownList and it’s DrawMode to OwnerDrawFixed.

image

Things become a little more interesting. The DataSource of the cboPriority will be a List<> containing the PriorityObjects we choose to. This may sound weird now, but in a few lines of code you will get the idea. Add a new item to the project of type class and name it PriorityObject.cs. Add the following code into it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace ColoredCombo
{
    public class PriorityObject
    {
        public string Name { get; set; }
        public Color Color { get; set; }

        public PriorityObject(string name, Color color)
        {
            Name = name;
            Color = color;
        }
    }
}

Each object of type PriorityObject will have a Name  and a Color. To have a list of these object we will add a new class to the project, named PriorityCollections.cs

using System.Collections.Generic;
using System.Drawing;

namespace ColoredCombo
{
    public class PriorityCollections
    {
        public static List<PriorityObject> GetPriorities() 
        {
            List<PriorityObject> lst = new List<PriorityObject>();
            
            lst.Add(new PriorityObject( "High", Color.Red));
            lst.Add(new PriorityObject( "Medium", Color.Orange));
            lst.Add(new PriorityObject( "Low", Color.YellowGreen));
            
            return lst;
        }
    }
}

This being done, we will proceed in completing the combo box master piece. Go back to Form1, right click on cboPriority and choose Properties. On Properties window press the Events button (you know… the little one with the lightning on it) and add a new event for Draw item (cboPriority_DrawItem).

In this event, using GDI+, we will draw each combo box item manually. Each item will be composed from a small square which will be filled with the right color and a text contain the priority. But what is GDI+ ? You may ask… Microsoft Windows GDI+ is a class-based API that enables applications to use graphics and formatted text on both the video display and the printer. Applications based on the Microsoft Win32 API do not access graphics hardware directly. Instead, GDI+ interacts with device drivers on behalf of applications.

First we need to give a DataSource to the ComboBox. For this I will make a simple method and call it in form load.

 private void GetPriorityList()
        {
            lstPriority = PriorityCollections.GetPriorities();
            cboPriority.DataSource = lstPriority;
            cboPriority.ValueMember = "Color";
            cboPriority.DisplayMember = "Name";
        }    

where  lstPriority is declared as a private variable;

Run the project and see the results. It should look like this:

image Nothing spectacular until now. Prepare yourself to do some drawing. In the cboPriority_DrawItem created before add the next code:

private void cboPriority_DrawItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
            if (e.Index >= 0)
            {
                Color clr = lstPriority[e.Index].Color;
                using (Brush brush = new SolidBrush(clr))
                {
                    e.Graphics.FillRectangle(brush, e.Bounds.X, e.Bounds.Y, 14, 14);
                }

                using (Brush brush = new SolidBrush(e.ForeColor))
                {
                    e.Graphics.DrawString(lstPriority[e.Index].Name.ToString(), e.Font, brush, e.Bounds.Left + 16, e.Bounds.Top);
                }
                e.DrawFocusRectangle();

            }
        }

As you can seem in clr variable I take the current drawn item Color property. Creating a solid brush with this color, I draw a rectangle of 14×14 pixels. I also create a string with current item Name property and I draw it beside the created rectangle (e.bounds.Left+16).

Run the project and prepare yourself to be amazed:

image