An easy way to use font icon in Android

Kevin Chung
4 min readMay 27, 2021

--

Photo by Harpal Singh on Unsplash

When design an App, it is quite often that need icons for button decoration or state indication. I used to search on icon websites such like flaticon or icons8 and download the required PNG files and put them into drawable resource folder.

Everything is fine at begin, but some problems appears soon.

Display: downloaded PNG files may not display perfectly mapping on different screen densities

Style inconsistency: icon set may not rich enough cause you can not find required icon with same style

Efficiency: before can use icon, you have to download file and copy into project folder

Resource management: have to clean up the icon files which looks not good after integration

I finally found a better solution, that is

“Icon Font”

Icon font is a regular font but show an icon rather than a character when displayed. There have many free icon fonts could be easily found, such like Awesome and Material Design Icon. The font icons could contains several thousands icons and could be easily to scale any size.

Since it is a normal font, the simplest way to integrate it in Android is use TextView.

First, copy icon font into “res/font” folder. For example, material design icon(mdifont.ttf). Then create a xml file (ex. mdi.xml) and specify android:font attribute to the name of font.

Second, create a TextView in layout file. Assign the font xml just created to android:fontFamily and the icon code you like to show to android:text.

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/mdi"
android:textSize="60dp"
android:text="&#xF08C9;"
/>

Then run it.. an elegant icon shows. You can also change its color, size, padding by related TextView attributes.

Although this solution is quite simple, however there still has some drawbacks for me:

  • An icon code looks like “&#xF08C9;” is hard to know what it should look while reviewing
  • A drawable object is sometimes better as a decoration for other views, such like ImageButton

To resolve these problems, I implemented a simple library MdiDrawable on GitHub. This library is based on Material Design Icon font which could generate drawable programmatically by a string resource id. It looks like…

imageview.background = MdiDrawable(context)
.stringId(R.string.mdi_alert_decagram)
.create()

There have other configurations could be used for more effects

imageview.background = MdiDrawable(context)
.stringId(R.string.mdi_android)
.size(60)
.radius(60)
.iconColor(Color.BLUE)
.enableBackground(true)
.useGradient(Color.DKGRAY, Color.LTGRAY)
.stroke(width=2, color.BLACK, length=10, gap=2)
.shadow(color=Color.BLACK, radius=4, dx=10, dy=10)
.create()

Here comes the demo

If you prefer XML way, this library also provide MdiView allow you configure an icon in layout file.

<com.kevinchung.mdi_drawable.MdiView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/mdi_calendar"
android:textSize="40dp"
android:padding="4dp"
app:bgColor = "@color/blue_grey_600"
app:useGradient="true"
app:cornerRadius="6dp"
app:gradientStartColor="@color/blue_grey_600"
app:gradientEndColor="@color/blue_grey_100"
app:gradientOrientation="rightLeft"
app:strokeWidth="1dp"
app:strokeColor="@color/black"
/>

How it works

MdiDrawable come along with a string resource table which have all icons mapping. So that you can use more meaningful name such like R.string.mdi_bullseye_arrow instead of &#xF08C9; when specify an icon.

And you can benefit by the auto-complete feature when finding icon.

This string table is automatically converted from the CSS file in Material Design Icon package by this script file. You can also use same script file to get latest version font package and generate updated string table.

How this library generate drawable? Actually it just doing a really simple thing by runtime create a TextView. Then pass any related parameters (color/size/shadow..) into it and ask TextView to draw on a Canvas object. Finally, create a drawable from this Canvas.

context.let {
val tv = TextView(it)
tv.setTextColor(config.iconColor)
tv.typeface = ResourcesCompat.getFont(it, R.font.mdi)
... val bitmap = Bitmap.createBitmap(
tv.width,
tv.height,
Bitmap.Config.ARGB_8888
)
var canvas = Canvas(bitmap)
tv.draw(canvas)
return BitmapDrawable(it.resources, bitmap)
}

End of story, hope this article helps. :)

--

--

Responses (1)