1
votes

I am trying to implement a custom font into my Xamarin forms app. The font is Quicksand-Regular from Google.

Checklist: Font has been added at different points to Fonts/, the root directory , and the Resources folder. The build action is set to BundleResource, and the output director has been tested with both Always Copy, and Do Not Copy. The Plist has been amended with UIAppFonts Quicksand-Regular.tff

The useable name of the font is just Quicksand but I tried referencing it in the app with both Quicksand and Quicksand-Regular. I have tried to add, Style TargetType="Label" Setter Property="FontFamily" Value="Quicksand" Style

To the app wide resource dictionary, as well as refer directly to the font on a label, both just specifying the FontFamily and referring to it as platform specific. The odd thing I'm seeing is that in the preview window it's working fine, both label and button text is being replaced correctly but this doesn't work runtime.

I believe then the resource isn't actually getting found or copied to the iOS project correctly but any suggestions would be appreciated.

2

2 Answers

0
votes

I can only list what I did to get a font working on iOS:

The font was MaterialIcons-regular.ttf

Added to resources folder

Build Action = BundleResources

Copy To Output Directory = Do not copy

Label FontFamily = "Material Icons" (note the space)

Add font to info.plist

<key>UIAppFonts</key>
<array>
    <string>MaterialIcons-Regular.ttf</string>
</array>

Here is a blog post listing the steps required on iOS. It says Copy to output directory should be Always copy. Not what I found but another possible stumbling block.

0
votes

In order to use custom fonts, you need to do the following:

** Shared Code **

Create a new class deriving from the element, you want to have displayed with a custom font, e.g. a Label:

CustomFontLabel.cs

public class CustomFontLabel : Label
{
}

Yes, it is basically an empty class.

Android Add the font (ttf file) to your App's assets (not resources!) and set the build action to "AndroidAsset".

now create a custom renderer in your android project:

CustomFontRenderer.cs

[assembly: ExportRenderer(typeof(CustomFontLabel), typeof(CustomFontRenderer))]
namespace MyNamespace.Droid.Renderer.Elements
{
    public class CustomFontRenderer: LabelRenderer
    {
        public CustomFontRenderer(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            TextView label = (TextView)Control;

            if (e.NewElement?.FontFamily != null)
            {
                Typeface font = null;
                // the try-catch block will ensure the element is at least rendered with default 
                // system font in Xamarin Previewer instead of crashing the view
                try
                {
                    font = Typeface.CreateFromAsset(AndroidApp.Application.Context.Assets, e.NewElement.FontFamily);
                }
                catch (Exception)
                {
                    font = Typeface.Default;
                }
                label.Typeface = font;
            }
        }
    }

iOS

Add the fonts to the resources folder and make sure that the build action is set to "BundleResource".

Next, add the font to the info.plist, for instance:

  <key>UIAppFonts</key>
  <array>
    <string>fontawesome.ttf</string>
    <string>OpenSans-Light.ttf</string>
    <string>OpenSans-Bold.ttf</string>
    <string>OpenSans-LightItalic.ttf</string>
    <string>OpenSans-Italic.ttf</string>
    <string>OpenSans-Regular.ttf</string>
    <string>Lato-Bold.ttf</string>
    <string>Lato-Regular.ttf</string>
  </array>

Now add a custom Renderer:

CustomFontRenderer.cs

[assembly: ExportRenderer(typeof(CustomFontLabel), typeof(CustomFontRenderer))]
namespace MyNamespace.iOS.Renderer.Elements
{
    public class CustomFontRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null && e.NewElement.FontFamily != null)
            {
                e.NewElement.FontFamily = e.NewElement.FontFamily.Replace(".ttf", "");
            }
        }
    }
}

Now back in your forms view, you can insert your custom label:

<elements:CustomFontLabel Text="A simple label using font family 'Lato'" FontFamily="Lato-Bold.ttf" />