Implement Custom fonts using Effects in Xamarin Forms

Recently I had requirement to use custom fonts (a font other than one present in device) in one of my Xamarin forms app, so I looked for the same in Xamarin documentation and found that the example is using Custom render to implement the same in android app. This would have been fine before Xamarin Forms 2.3 was released, but now we have an awesome feature called Effects to implement these kind of small platform specific customization, so that we don’t need to create a new custom control for every small platform specific changes needed in the control. This article will show how to implement custom fonts in Android iOS & UWP apps using effects.

So First create a new project in Xamarin/Visual Studio then perform the changes/additions mentioned in following sections.

Changes in PCL project:

  1. Create a new class file named ‘CustomFontEffect’ and add following code to it:
    
     public static class CustomFontEffect
        {
            public static readonly BindableProperty FontFileNameProperty = BindableProperty.CreateAttached("FontFileName", typeof(string), typeof(CustomFontEffect), "", propertyChanged: OnFileNameChanged);
            public static string  GetFontFileName(BindableObject view)
            {
                return (string)view.GetValue(FontFileNameProperty);
            }
    
            public static void SetFontFileName(BindableObject view, string value)
            {
                view.SetValue(FontFileNameProperty, value);
            }
            static void OnFileNameChanged(BindableObject bindable, object oldValue, object newValue)
            {
                var view = bindable as View;
                if (view == null)
                {
                    return;
                }
                view.Effects.Add(new FontEffect());
            }
            class FontEffect : RoutingEffect
            {
                public FontEffect() : base("Xamarin.FontEffect")
                {
                }
            }
    
        }
    

    In the above mentioned code we are creating a custom effect where we are creating a new property named ‘FontFileName’ for the Bindable object to which the effect will be attached. The implementation of this effect will have to be written in Platform specific projects.

  2. In order to implement custom fonts using XAML, set the ‘FontFamily’ of label as per following XAML code:
        <Label Text="This custom font 'AbeatByKai' (First in selection picker) is Set in XAML as an Example, This will not change. " local:CustomFontEffect.FontFileName="abeatbyKaiRegular" >
          <Label.FontFamily>
            <OnPlatform x:TypeArguments="x:String">
              <OnPlatform.iOS>AbeatByKai</OnPlatform.iOS>
              <OnPlatform.Android></OnPlatform.Android>
              <OnPlatform.WinPhone>/Assets/Fonts/abeatbyKaiRegular.ttf#AbeatByKai</OnPlatform.WinPhone>
            </OnPlatform>
          </Label.FontFamily>
        </Label>
    

    No font name is provided for Android platform as it requires the name of the font file without extension to create font in platform specific code, that name we are passing in the new property ‘FontFileName’ which is attached while attaching the effect to the control (code local:CustomFontEffect.FontFileName=”abeatbyKaiRegular” )
    The font name to be used in iOS & UWP/WinPhone (after #) can be taken out from the font file by opening it in font installer as highlighted in following screenshot.
    Font Details

  3. In order to implement custom fonts in code behind use following c# code:

          Device.OnPlatform(
            iOS: () =>
            {
                lblSample.FontFamily = "AbeatByKai";
            },
            Android: () =>
            {
                CustomFontEffect.SetFontFileName(lblSample, "abeatbyKaiRegular");
            },
            WinPhone: () =>
            {
                lblItalics.FontFamily = "/Assets/Fonts/abeatbyKaiRegular.ttf#AbeatByKai";
            }
                );
    

Changes in iOS project:
Implementation of custom fonts in iOS is pretty strait forward, so just mentioning about the same for the sake of documentation πŸ™‚

  • Copy the the custom fonts you need to use in ‘Resources’ folder in iOS specific project as shown in below screenshot (I kept the file in a separate folder for sake of clarity you can put them directly in ‘Resources’ folder also if you want)
  • 2372016iOSPath

  • Change the ‘Build Action’ property of every font file as ‘BundleResource’ and ‘Copy to output directory’ to ‘always copy’
  • 2372016iOSFontType

  • Open the ‘info.plist’ file in XML editor by right clicking on it and selecting ‘Open With’ option and then selecting XML (Text) Editor from the list of editors given as shown in below screenshots
  • 2372016OpenTypeSelnfoDotPlist

  • Add new XML key element ‘UIAppFonts’ and list your custom fonts in array in ‘info.plist’ as per following screenshot
  • 2372016InfoDotPlist

That’s it your iOS application is ready for showing the custom fonts, no effect implementation needed for this project.

Changes in Android project:
Android project is the main one for which we are writing this blog πŸ™‚

  1. Copy the the custom fonts you need to use in ‘Assets’ folder in android specific project as shown in below screenshot (I kept the file in a separate folder for sake of clarity you can put them directly in ‘Assets’ folder also if you want)
  2. 2372016AndroidPath

  3. Change the ‘Build Action’ property of every font file as ‘AndroidAsset’ and ‘Copy to output directory’ to ‘Copy Always’
    2372016AndroidFontType
  4. And finally write the implementation for the effect which we have declared in PCL project, for that add a new class file named ‘FontEffect.cs’ to the project and update it with the following code:

    using System;
    using CustomFontEx.Droid;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    using Android.Widget;
    using Android.Graphics;
    using System.ComponentModel;
    
    [assembly: ResolutionGroupName("Xamarin")]
    [assembly: ExportEffect(typeof(FontEffect), "FontEffect")]
    namespace CustomFontEx.Droid
    {
        public class FontEffect : PlatformEffect
        {
            TextView control;
            protected override void OnAttached()
            {
                try
                {
                    control = Control as TextView;
                    Typeface font = Typeface.CreateFromAsset(Forms.Context.Assets, "Fonts/" + CustomFontEffect.GetFontFileName(Element) + ".ttf");
                    control.Typeface = font;
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
                }
            }
    
            protected override void OnDetached()
            {
            }
    
            protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
            {
                if (args.PropertyName == CustomFontEffect.FontFileNameProperty.PropertyName)
                {
                    Typeface font = Typeface.CreateFromAsset(Forms.Context.ApplicationContext.Assets, "Fonts/" + CustomFontEffect.GetFontFileName(Element) + ".ttf");
                    control.Typeface = font;
                }
            }
    
        }
    }
    

Changes in UWP project:
Implementation of custom fonts in UWP is more easier than & strait forward than iOS, so just mentioning about the same for the sake of documentation πŸ™‚

  • Copy the the custom fonts you need to use in ‘Assets’ folder in UWP specific project as shown in below screenshot (I kept the file in a separate folder for sake of clarity you can put them directly in ‘Assets’ folder also if you want)
  • 2372016UWPWindowsPath

  • Change the ‘Build Action’ property of every font file as ‘Content’ and ‘Copy to output directory’ to ‘Copy if newer’
  • 2372016UWPFontType

That’s it πŸ™‚ your UWP application is ready for showing the custom fonts, no effect implementation needed for this project too.

This is how sample application who code is published on Github looks on executing.

iOS Simulator
2372016iOSDemo
Android Simulator
2372016AndroidDemo
Windows 10 Simulator
2372016UWPDemo
Let me know if I has missed anything or have any suggestions/concerns/queries.

πŸ™‚ πŸ™‚ Happy Coding πŸ™‚ πŸ™‚

2 Comments

Leave a Reply

Your email address will not be published.


*