November 13, 2013

How to use icon-fonts in Android

There is popular web-technique for creating awesome icons - generate font with custom glyphs and use single unicode character with specified typeface.

Look here for example and let’s try to use this technique in Android.


NOTICE: This post describe details of implementation font-icons. Visit project summary page to learn more about released library - Android FontIcon Library.

Get demo on Google Play

Get it on Google Play

At first we need to consider, why we want to use it? I have two reasons which are quite important as for me.

1. Reduce .apk size by replacing 4 drawables by single glyph in font file.


Let’s calculate the total size of 5 randomly selected icons which were downloaded from Android Asset Studio.

ic_action_action_about
ic_action_content_discard
ic_action_content_edit
ic_action_social_cc_bcc
ic_action_social_chat


There are 4 files for each icon: mdpi, hdpi, xhdpi, xxhdpi. Total size of those 20 files is 33,8 kb (33824 b).

Approximately 6-8 kb for the one icon. But in some cases (when your icons have quite much details) they can take around 10 kb per one icon.


So, what about font size? Well, size of .ttf file which contains these icons takes 2,3 kb (2280 b). This is just 6% from .png files size! There is 30 kb saved only for 5 icons!


How many icons do you have in your application? I have around 40 icons in my application.
Approximately (40 / 5) * 30 = 240 kb of saved space. Not so much, but not so little. Let’s go to the second advantage of using icon fonts.

2. As css-tricks.com said: you can easily change the size, color, add shadow and glow effect.


You do not need anymore to make different .png file for pressed or selected icons - just change the text color! Do not add same .png files with different color, saved size is multiplied by 2.

Well, let's try to do this. How to create custom font with icons?

There are many online services which can generate such fonts. They also provided a lot of free icons presets. I'm using this one.

If you have your own icons you can import them as well. All you need are set of .svg files with your icons. If you are working with proficient designer, he can generate .svg files for you using Adobe Illustrator. In other case you can convert .png to .svg. There are many tools and online services for doing this. I'm using this one. Remember to specify option Monochrome when converting your .png.

In my example I will use icons from available presets.

After the few steps on fontastic app, you will be able to download .zip with your fonts and demo for web:


For Android we will use .ttf file and some information from style.css.

When we open styles.css we can find next lines:

.ic-quote:before {
    content: "\e000";
}
.ic-users:before {
    content: "\e001";
}
.ic-info:before
{
    content: "\e002";
}
.ic-edit:before
{
    content: "\e003";
}
.ic-delete:before
{
    content: "\e004";
}


These are styles with unicode characters of our icons. We will re-write them as strings resources like this:


NOTICE: Now there is available automatic parser  FontIcon-Prepare.

res/values/icons.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="ic_quote">&#xe000;</
string>

    <string name="ic_users">&#xe001;</string>
    <string name="ic_info">&#xe002;</string>
    <string name="ic_edit">&#xe003;</string>
    <string
name="ic_delete">&#xe004;</string>
</
resources>


File with icons place into assets:


assets/icons.ttf

Now, check full example on github.


There are two classes: FontIconDrawable and FontIconTypefaceHolder.

First one extends Drawable abstract class, second one is just the static storage for Typeface instace loaded from .ttf file.

Typeface is initialized in the Application.onCreate() method:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        FontIconTypefaceHolder.init(getAssets(), "icons.ttf");
    }
}


Using of FontIconDrawable is very simple, for example in Fragment.onCreateView():

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle state) {
    Drawable[] icons = new Drawable[]{
        FontIconDrawable.inflate(getResources(), R.xml.ic_quote),
        FontIconDrawable.inflate(getResources(), R.xml.ic_users),
        FontIconDrawable.inflate(getResources(), R.xml.ic_info),
    };


    // use drawables for any purpose
}

What are R.xml.ic_quote, R.xml.ic_users, etc? This is custom xml to simplify instantiation of FontIconDrawable.

Example:

res/xml/ic_delete.xml

<?xml version="1.0" encoding="utf-8"?>
<font-icon
        xmlns:android="http://schemas.android.com/apk/res-auto"
        android:text="@string/ic_delete"
        android:textSize="@dimen/icon_size"
        android:textColor="@android:color/white"
        />


Let's look at the results:




There is lot of possibilities of using font-based icons. Today I show just one way to use it. Next time I'll try to generalize this solution, to be most applicable and usable. 

Check updates on github.


Gradle dependency

Just add folowing lines in corresponding section of your build.gradle:

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.shamanland:fonticon:0.1.6'
}