3
votes

I need to specify different FontFamily for different Labels in my app. I need to use the default fonts (e.g. Roboto for Android and Helvetica for iOS) with their modifications (e.g. Light, Medium, Bold). As far as I understand I should be using Roboto-Light and Helvetica-Light to get the Light version of the fonts (same for Medium and Bold). In addition to this requirement I need to set the fonts in XAML (like described in documentation) so I end up with this code

<StackLayout BackgroundColor="#F8F8F8" Padding="0, 20, 0, 0">
<Label Text="Black" TextColor="#000000" >
  <Label.FontSize>
    <OnPlatform x:TypeArguments="x:Double"
                iOS="17"
                Android="16"
                WinPhone="16" />
  </Label.FontSize>
  <Label.FontFamily>
    <OnPlatform x:TypeArguments="x:String">
      <OnPlatform.iOS>Helvetica-Black</OnPlatform.iOS>
      <OnPlatform.Android>Roboto-Black</OnPlatform.Android>
      <OnPlatform.WinPhone></OnPlatform.WinPhone>
    </OnPlatform>
  </Label.FontFamily>
</Label>
<Label Text="Light" TextColor="#000000">
  <Label.FontSize>
    <OnPlatform x:TypeArguments="x:Double"
                iOS="17"
                Android="16"
                WinPhone="16" />
  </Label.FontSize>
  <Label.FontFamily>
    <OnPlatform x:TypeArguments="x:String">
      <OnPlatform.iOS>Helvetica-Light</OnPlatform.iOS>
      <OnPlatform.Android>Roboto-Light</OnPlatform.Android>
      <OnPlatform.WinPhone></OnPlatform.WinPhone>
    </OnPlatform>
  </Label.FontFamily>
</Label>
<Label Text="Medium" TextColor="#000000" >
  <Label.FontSize>
    <OnPlatform x:TypeArguments="x:Double"
                iOS="17"
                Android="16"
                WinPhone="16" />
  </Label.FontSize>
  <Label.FontFamily>
    <OnPlatform x:TypeArguments="x:String">
      <OnPlatform.iOS>Helvetica-Medium</OnPlatform.iOS>
      <OnPlatform.Android>Roboto-Medium</OnPlatform.Android>
      <OnPlatform.WinPhone></OnPlatform.WinPhone>
    </OnPlatform>
  </Label.FontFamily>
</Label>
<Label Text="Bold"  TextColor="#000000">
  <Label.FontSize>
    <OnPlatform x:TypeArguments="x:Double"
                iOS="17"
                Android="16"
                WinPhone="16" />
  </Label.FontSize>
  <Label.FontFamily>
    <OnPlatform x:TypeArguments="x:String">
      <OnPlatform.iOS>Helvetica-Bold</OnPlatform.iOS>
      <OnPlatform.Android>Roboto-Bold</OnPlatform.Android>
      <OnPlatform.WinPhone></OnPlatform.WinPhone>
    </OnPlatform>
  </Label.FontFamily>
</Label>

However, the result in Android is unexpected. The FontFamily of the different Labels is not changed. They all look the same.

Android

The same code in iOS works as expected

enter image description here

My question is: How to get the Roboto-Light, Roboto-Medium and Roboto-Bold fonts in my Android app if following XAMARIN documentation does not work?

4

4 Answers

4
votes

Update:

I did not see that you were using API 18 / 4.3 the first time (in the title bar of your emulator), thought you were loading them as custom assets for older android versions. Since roboto is the default font since 4.1, you can use them as:

  • sans-serif
  • sans-serif-light
  • sans-serif-condensed
  • sans-serif-thin (4.2+)

Original:

https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/fonts/

Xamarin.Forms for Android does not currently expose the ability to set the font to a custom font file, so custom renderers are required. When writing the renderer for the Android platform, create a Typeface instance that references a custom font file that has been added to the Assets directory of the application (with Build Action: AndroidAsset).

[assembly: ExportRenderer (typeof (MyLabel), typeof (MyLabelRenderer))]
namespace WorkingWithFonts.Android {
    public class MyLabelRenderer : LabelRenderer {
        protected override void OnElementChanged (ElementChangedEventArgs<Label> e) {
            base.OnElementChanged (e);
            var label = (TextView)Control; // for example
            Typeface font = Typeface.CreateFromAsset (Forms.Context.Assets, "SF Hollywood Hills.ttf");
            label.Typeface = font;
        }
    }
}
1
votes

I did overwrite the default Renderer for all views I needed it for.

That way you can use XAML code like you intended to:

<Label FontFamily="Arial" Text="Hi there" />

Here is an example for Label.

[assembly: ExportRenderer (typeof (Label), typeof (MyLabelRenderer))]
namespace MyApp.Droid
{
    public class MyLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);

            if ( !String.IsNullOrEmpty(Element.FontFamily) )
                Control.Typeface = Typeface.CreateFromAsset(Forms.Context.Assets, "Fonts/" + Element.FontFamily + ".otf");
        }
    }
}

Of course you need to map that to the location where you embedded the custom font. In my case Assets/Fonts/Arial.otf.

0
votes

Please use below render, to load custom font in label, please make sure that you will put your font file in fonts folder in assets folder of android project to define similar path for all platform

[assembly: ExportRenderer(typeof(Label), typeof(CustomLabelRenderer))]
namespace MyApp.Droid.Renderer
{
    public class CustomLabelRenderer : LabelRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement != null)
                if (!String.IsNullOrEmpty(e.NewElement.FontFamily))
                    Control.Typeface = Typeface.CreateFromAsset(Forms.Context.Assets, "Fonts/" + Element.FontFamily);
        }
    }
}

xaml of label control, please make sure that font file is available in font folder

<Label FontFamily="Roboto-Light.ttf" Text="Hi there" />
0
votes

2020 Update, Xamarin.Forms 4.5 now supports custom fonts embedded in one place (shared UI project) and exported via ExportFont attribute: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/text/fonts#use-a-custom-font - iOS, Android and UWP. For macOS and WPF you still have to go longer path as described below.

As of 2018, in Xamairn.Forms, there's no need for platform renderers. The steps are:

  1. Download TTF files and bundle them as resources with each platform project.
  2. Reference the fonts from within Xamarin.Forms shared project, taking into account the peculiarities of each platform (naming conventions for addressing resources and font families).
  3. Apply the fonts to Xamarin.Forms controls.

Here's detailed description on how to add and apply custom fonts in macOS, WPF and Android.