Tuesday, September 29, 2015

FontAwesome using Xamarin Forms and Android

FontAwesome is, well, awesome... And be warned, this is kind of a hack.

EDIT: Here's the iOS version, but please read this post first anyhow.

On Android, it's a bit of a hassle use FontAwesome. This blog post is about how to use Font Awesome in the simplest way possible. It's as easy as using a Label once set up.

The hack is simple. We use a custom renderer that looks at the Label in question, determines if there is one character in the text field and if that character has the value of 0xf000 or higher. If so, we replace the font with FontAwesome.

Since the icons all begin at 0xf000 or higher, the custom renderer will make sure that the correct font is used.

The first label in the example below will simply print out the text. The second label will show a map marker icon using a single unicode character and the third references a local static object that maps all the icons to a friendly name. The static object is in the sample project.

            <!-- Business as usual -->
            <Label Text="Just Normal Text" />

            <!-- A Map marker using a single character -->
            <Label Text="&#xf041;" FontSize="40" />

            <!-- Using a resource -->
            <Label Text="{x:Static local:FontAwesome.FAPhone}" FontSize="40" />


This will result in the following screen.



Here's how you do it.

Download the font

Download the FontAwesome font and drop it in your Asset folder for the Droid project. Don't forget to check that the build type is set to AndroidAsset.

Create a custom renderer

The magic goes here. In the Droid project, create a custom renderer that looks like this.

[assembly: ExportRenderer(typeof(Label), typeof(AwesomeRenderer))]

namespace Awesome.Droid
{
    public class AwesomeRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            var label = (TextView)Control;

            var text = label.Text;
            if(text.Length > 1 || text[0] < 0xf000)
            {
                return;
            }

            var font = Typeface.CreateFromAsset(Xamarin.Forms.Forms.Context.ApplicationContext.Assets, "fontawesome.ttf");
            label.Typeface = font;
        }
    }
}

Summary



18 comments:

  1. Replies
    1. I have a little trick for iOS as well where I use a style to reference the font. I'll try to make a blog post about that as soon as possible. On iOS you have to reference the font in the info.plist file (https://blog.xamarin.com/custom-fonts-in-ios/) and then simply reference it in your Xaml. So just add FontFamily="FontAwesome" on the Label after adding the font. Android will ignore it, hence the need of the hack described in this post. But iOS will pick it up. You could also create a custom renderer in the iOS project to set the font based on the same rules.

      Delete
    2. Now it is: http://www.johankarlsson.net/2015/10/fontawesome-using-xamarin-forms-and-ios.html

      Delete
  2. Did you mean "Xamarin Forms and Xamarin Android"?

    ReplyDelete
    Replies
    1. No, there is no difference between Xamarin Android and Android. They are both native android. It's just a matter of tooling. So the title is correct. :)

      Delete
    2. The requirement of MVP is to contribute to the community, so its easier to to create an unfinished blog thats ticks that box, then to provide a how for the iOS implementation.

      Delete
    3. Yes, but this post is complete from an android perspective. On iOS it isn't really that hard if you just read up on Custom Fonts. I would be writing copies of other peoples posts. And believe it or not, but we all do have regular jobs that takes up a lot of time.

      I like to focus on specific issues. FontAwesome is an issue on android, but not on iOS. Here's how you do it: https://blog.xamarin.com/custom-fonts-in-ios/

      Delete
    4. Here's an iOS version of the same thing. We lazy MVPs never get things done so WP is still missing. ;) http://www.johankarlsson.net/2015/10/fontawesome-using-xamarin-forms-and-ios.html

      Also, I moved the sample code to github instead for easier updates and reference.
      Have a great day!

      Delete
  3. I have few question regarding this:

    1. Can these icon auto resize at the large size screen
    2. Can we fill a particular color in icon? If yes, please let me know how ?
    3. These icons are only apply on TextView or Lable, I want to apply it on Image View. Is it possible ?

    ReplyDelete
    Replies
    1. Hi!
      1) You would have to create some kind of property in your ViewModel (or another helper) to adjust after screen size and bind that to the font size. Check out the second part of the post at http://www.johankarlsson.net/2015/10/fontawesome-using-xamarin-forms-and-ios.html
      2) Yes, TextColor="Red" or TextColor="#334455"
      3) No it's not, since FontAwesome is a font, It needs to render like text. So any control that renders text would do. An image displays a bitmap so that wouldn't work.

      Delete
  4. Hi I have a question about adding an image/icon to a list view

    // I'm using Xamarin
    // I can pull in the FontAwesome file
    Typeface font = Typeface.CreateFromAsset(Application.Assets, "FontAwesome.ttf" );

    // and Create my list Adapter
    items = new string[] { "row1", "row2", "row3", "row4"};
    ListAdapter = new HomeScreenAdapter(this, items);

    // How do I assign the one character Font to each row,
    // for example say I want a calculator icon in front of "row1" and something different for the next row
    // fa-calculator []

    ReplyDelete
    Replies
    1. Anytime you use FontAwesome you have to render them in a control that show text. For example a TextView control. You also need the unicode character that corresponds to the icon you are trying to show.

      So you need to do two things when each deflating each row. (if you have an axml file for the row and the HomeScreenAdapter deflates them).

      1) Set the icon
      myTextview.Text = FontAwesome.FAPhone; // Given that you have a static class that contains the character codes. (Download sample)

      2) Set type typeface
      myTextview.Typeface = font;

      Delete
  5. Hi Johan, I was wondering if there was a way to make this happen:
    Label Text=" Just Normal Text " FontSize="40"
    I'm using Xamarin forms and the icon shows up for me in iOS but in android the icon isn't visible but only the text "Just Normal Text" shows up.
    Thanks

    ReplyDelete
  6. Hi is it available for Windows phone ?

    ReplyDelete