James Montemagno
James Montemagno

Live, Love, Bike, and Code.

Tags


Twitter


James Montemagno

Using Font Icons in Xamarin.Forms: Goodbye Images, Hello Fonts!

James MontemagnoJames Montemagno

My entire mobile development career I have gone all in on using device specific images and icons. These are properly scaled and sized images that fit @1x, @2x, @3x, hdpi, xhdpi, xxhdi, and so on, which are great because they are super optimized for each platform. The reason I do this was because it gives very consistent look and feel to an app across all of the different form factors of the devices the app may run on. It also happens to be the official way that Google, Apple, and Microsoft tell you to do it and they even give you tools like the Asset Studio to help you generate them. However, my eyes have been opened and I am all in on FONTS! Yes... FONTS! I bet you thought I was going to say SVG, but NO, FONTS!

fonts

I mean look at all of those beautiful icons right there. I bet you thought they were images... nope those are being generated from a font! The great part about fonts like this is that they bundle tons of icons into a single file and it is really easy to access them with a specific code. additionally, since they are a font they should scale properly across different form factors :)

And up until a few weeks ago, I had no idea that Xamarin.Forms had great built in support for them. So, let's take a look at how to integrate them.

Import the Font

While I was working on a Xamarin.Forms app I got a great pull request that integrated Material Design Icons into the app. It was my first real experience seeing custom fonts to remove a bunch of images that were the same on each platform. All you need to do is grab the ttf file and add it to the correct location.

  • Android: Add it to the Assets folder and ensure it is marked as an AndroidAsset
  • iOS: Add the font file with Build Action: BundleResource, and update the Info.plist file (Fonts provided by application, or UIAppFonts, key).
  • UWP: Add the file to /Assets/Fonts/ and make sure it is marked as Content

Access Font Family

To access the fonts directly it is a bit quirky. You need to specify the correct value for each platform as to where the font lives. Since they are different on each platform and we don't want to write a bunch of code every time, we can simply put an OnPlatform key in our application resources:

<OnPlatform x:Key="MaterialFontFamily" x:TypeArguments="x:String">
    <On Platform="iOS" Value="Material Design Icons" />
    <On Platform="Android" Value="materialdesignicons-webfont.ttf#Material Design Icons" />
    <On Platform="UWP" Value="Assets/Fonts/materialdesignicons-webfont.ttf#Material Design Icons" />
</OnPlatform>

Turn Font to Code

Now, we need to access these fonts! You will need the specific codes for each icon in the font. Luckily, Andrei wrote an awesome tool to convert a font file to code called IconFont2Code:

FontToCode

Text or FontImageSource

What is great now is that we can set any control that has a FontFamily associated with it and simply set the Text property.

<Label FontFamily="{StaticResource MaterialFontFamily}" Text="{Binding Car"}/>

If you want to use the font for an Image, the new FontImageSource can be used:

<FontImageSource
            FontFamily="{DynamicResource MaterialFontFamily}"
            Glyph="{Binding Car}"
            Size="44"
            Color="{StaticResource PrimaryColor}" />

To use the font icons you can do it via a binding to the code that was generated like I did above, or to an escaped string in XAML. Let's look at some examples.

Access from Bindings

One thing that I think is really cool is that since you can use these fonts on any control that has a text property, it means you can use it on a Button!

On my Hanselman.Forms app we have a list of social links that we want to display as icons. Here is our source:

SocialItems = new List<SocialItem>
{
    new SocialItem
    {
        Icon = IconConstants.TwitterCircle, // "\uf547"
        Url = "https://www.twitter.com/shanselman"
    },
    new SocialItem
    {
        Icon = IconConstants.FacebookBox, // "\uf20d"
        Url = "https://www.facebook.com/shanselman"
    },
    new SocialItem
    {
        Icon = IconConstants.Instagram, //"\uf2fe"
        Url = "https://www.instagram.com/shanselman"
    }
};

In our XAML it couldn't be easier to data bind to it:

 <StackLayout
    BindableLayout.ItemsSource="{Binding SocialItems}"
    HorizontalOptions="CenterAndExpand"
    Orientation="Horizontal"
    Spacing="5">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Button
                Command="{Binding OpenUrlCommand}"
                Style="{StaticResource MaterialButton}"
                Text="{Binding Icon}" />
        </DataTemplate>
    </BindableLayout.ItemTemplate>
</StackLayout>

Social

Access Directly in XAML

When you want to directly access one of the fonts from XAML you will need to escape the key. So, if we were to convert the car from C# to escaped string:

public const string Car = "\uf10b";

Turns to:

<x:String x:Key="Play">&#xf10b;</x:String>

Then, if we wanted to use it on an Image the code would reference this key:

<Image
    Grid.Column="2"
    HeightRequest="44"
    HorizontalOptions="Center"
    VerticalOptions="Center"
    WidthRequest="44">
    <Image.Source>
        <FontImageSource
            FontFamily="{DynamicResource MaterialFontFamily}"
            Glyph="{StaticResource Play}"
            Size="44"
            Color="{StaticResource PrimaryColor}" />
    </Image.Source>
</Image>

Icons

When Not To Use Fonts

In this instance I am using fonts that are icons inside of the application that are reasonable to look and feel exactly the same across every platform. My recommendation as always is to use the platform look and feel for icons in toolbars and tabs. This will ensure your users have the best experience. Also, be aware that they will add some size to your app (material design icons was around 500KB!). Beyond that I say go for it :)

Read More

Checkout the Hanselman.Forms app on GitHub and see the work in progress with the new icons! Also, be sure to read through the great Font documentation for Xamarin.Forms


Tags



Live, Love, Bike, and Code

Checkout my monthly newsletter that you should subscribe to!

Comments