Xamarin.forms: FontImageSource does not work with Glyph and custom font icons for iOS App

Created on 7 Feb 2020  路  16Comments  路  Source: xamarin/Xamarin.Forms

Description

Steps to Reproduce

  1. I added the font to the Resouces folder of the iOS project
  2. Set the Build Action to 'BundledResource'
  3. Referenced the file in the info.plist file for the 'UIAppFonts' key
  4. Add a Image control to a Xaml page and set the fontfamily using FontImageSource. Reference the font icon by its name
    5 Set the 'Glyph' to a special code for a font icon within the font family
  5. Build and debug the project on an iOS simulator or phone. The font icon does not show

Expected Behavior

  1. When you Build and debug the project on an iOS simulator or phone. The correct font icon should display in the image control added to the xamarin page

Actual Behavior

  1. When you Build and debug the project on an iOS simulator or phone. The correct font icon does not show in the image control added to the xamarin page. Instead an icon with a question mark is displayed

Basic Information

  • Version with issue:
  • All iOS devices and simulators

  • Last known good version:

  • N/A

  • IDE:

  • Visual Studio for Mac 8.4.4 (build 91)

  • Platform Target Frameworks:

    • iOS: lastest stable thats available as of today's date

    • Android: Not applicable

    • UWP: Not applicable
  • Android Support Library Version: Not applicable

  • Nuget Packages:

  • Xamarin Forms 4.3.0.908675 - 4.4.0.991640 ( tested versions)
  • Xamarin.Essentials 1.3.1

  • Affected Devices:

  • All iOS devices

Screenshots

N/A

Reproduction Link

Link to sample project: https://1drv.ms/u/s!AlQcNqmWUARrtQocxHqiuvF2vGCB

Workaround

  1. N/A
fonticon iOS 馃崕 unverified bug

Most helpful comment

Hi, have tried to add materialdesignicons-webfont.ttf as embedded font, as described here: https://devblogs.microsoft.com/xamarin/embedded-fonts-xamarin-forms/

And i have the same issue, removing the hyphen from the font filename did not help.

Description

Steps to Reproduce

  1. Add the font file (otf or ttf) to your shared project and set the Build Action to EmbeddedResource (https://materialdesignicons.com/)
  2. Add ExportFont attribute in your shared project, using App.xaml.cs
[assembly: ExportFont("materialdesignicons-webfont.ttf", Alias = "Material")]
  1. It is not required to referenced the font file in info.plist on iOS
  2. Add a Label and a Image control to a Xaml page
    Set the FontFamily, on the image control using FontImageSource. Reference the font by the defined Alias and set the 'Glyph' on FontImageSource to a special code for a font icon within the font family
        <Label FontFamily="Material" Text="&#x000f0004;" />
        <Image>
            <Image.Source>
                <FontImageSource FontFamily="Material" Glyph="&#x000f0004;" />
            </Image.Source>
        </Image>

Expected Behavior

When you Build and debug the project on any of the supported plattforms:

  1. The correct font icon should display in the label text
  2. The correct font icon should display in the image control

Actual Behavior

When you Build and debug the project on an iOS simulator or phone:

  1. The correct font icon is shown in the label text
  2. The correct font icon does not show in the image control. Instead an icon with a question mark is displayed

When you Build and debug the project on an Android simulator or phone:

  1. The correct font icon is shown in the label text
  2. The correct font icon is shown in the image control

When you Build and debug the project for UWP:

  1. The correct font icon does not show in the label text. Instead an rectangular icon is displayed
  2. The correct font icon does not show in the image control. Instead an rectangular icon is displayed

Basic Information

  • Version with issue:

All iOS devices and simulators, Windows 10

  • Last known good version:

N/A

  • IDE:

Visual Studio 16.5.3

Platform Target Frameworks:

  • iOS: 13.4.1
  • Android: Working / 9.0 Pie
  • UWP: 1809 / 17763
  • Nuget Packages:
  • Xamarin Forms 4.5.0.617
  • Xamarin.Essentials 1.5.2

Screenshots

N/A

Reproduction Link

N/A

Workaround

  1. use OnPlatform in ResourceDictionary
    <OnPlatform x:Key="Material" x:TypeArguments="x:String">
        <On Platform="iOS" Value="Material Design Icons" />
        <On Platform="Android" Value="Material" />
        <On Platform="UWP" Value="Material Design Icons" />
    </OnPlatform>
  1. and then for FontFamily
        <Image>
            <Image.Source>
                <FontImageSource FontFamily="{DynamicResource Material}" Glyph="&#x000f0004;" />
            </Image.Source>
        </Image>

But on iOS i needed to navigate of the page and then back for the correct image source icon to be shown

All 16 comments

I had the same issue and found a workaround that worked for me:

Instead of setting the glyph during runtime, you can try to create a parent for the fonticon, then create a new icon every time you want to change the glyph and attach it to the parent

IconParent.Children.Clear();

var source = new FontImageSource
{
    Glyph = (string)Application.Current.Resources[glyph],
    FontFamily = (OnPlatform<string>)Application.Current.Resources["icon-default"],
    Size = 20
};

var icon = new TintedImage
{
    Source = source,
    TintColor = (Color)Application.Current.Resources["IconColor"],
    Margin = 12
};

IconParent.Children.Add(icon);

I tried doing less by just creating a new FontImageSource and add it to the same TintedIamge, but it doesn't work. The icon must be a new View to work.

Hope it helps

@Kode4Hue try removing the "Resources/" in your info.plist file

<key>UIAppFonts</key>
    <array>
        <string>Resources/Ionicons.ttf</string>
    </array>

Mine looks like this

 <key>UIAppFonts</key>
  <array>
    <string>ionicons.ttf</string>
  </array>

And it works great

This still is an issue. I removed 'Resources' and still does not work @PureWeen. In fact, I also tried the new custom font approach available in Xamarin.Forms 4.5. Added the font to the shared library and exported it in AssembyInfo.cs. Works in Android, nothing in iOS.

@samhouts This should be re-opened

@PureWeen ok it WORKS! I was testing two sets of fonts: 1) ionicons.ttf and materialdesignicons-webfont.ttf.. It started working for 'ionicons.ttf'. I had to rename 'materialdesignicons-webfont.ttf' to 'materialdesignicons.ttf'. Removing the hyphen from the file name solved my issues

@Kode4Hue great to hear!!

I also encountered this problem an my solution was as follows:
1) export font in AssemblyInfo.cs
[assembly: ExportFont("fontAwesomeIcons.ttf", Alias = "FontAwesomeIcons")]
2) Use Font ImageSource:

Very important: The font family can be the alias (FontAwesomeIcons) on android, however ios requires that you use the actual font name! This may be different from the font file name! I opened the ttf file and saw the name was "Font Awesome 5 Free Solid". I then had to remove the "Solid" part and it worked!

Hi, have tried to add materialdesignicons-webfont.ttf as embedded font, as described here: https://devblogs.microsoft.com/xamarin/embedded-fonts-xamarin-forms/

And i have the same issue, removing the hyphen from the font filename did not help.

Description

Steps to Reproduce

  1. Add the font file (otf or ttf) to your shared project and set the Build Action to EmbeddedResource (https://materialdesignicons.com/)
  2. Add ExportFont attribute in your shared project, using App.xaml.cs
[assembly: ExportFont("materialdesignicons-webfont.ttf", Alias = "Material")]
  1. It is not required to referenced the font file in info.plist on iOS
  2. Add a Label and a Image control to a Xaml page
    Set the FontFamily, on the image control using FontImageSource. Reference the font by the defined Alias and set the 'Glyph' on FontImageSource to a special code for a font icon within the font family
        <Label FontFamily="Material" Text="&#x000f0004;" />
        <Image>
            <Image.Source>
                <FontImageSource FontFamily="Material" Glyph="&#x000f0004;" />
            </Image.Source>
        </Image>

Expected Behavior

When you Build and debug the project on any of the supported plattforms:

  1. The correct font icon should display in the label text
  2. The correct font icon should display in the image control

Actual Behavior

When you Build and debug the project on an iOS simulator or phone:

  1. The correct font icon is shown in the label text
  2. The correct font icon does not show in the image control. Instead an icon with a question mark is displayed

When you Build and debug the project on an Android simulator or phone:

  1. The correct font icon is shown in the label text
  2. The correct font icon is shown in the image control

When you Build and debug the project for UWP:

  1. The correct font icon does not show in the label text. Instead an rectangular icon is displayed
  2. The correct font icon does not show in the image control. Instead an rectangular icon is displayed

Basic Information

  • Version with issue:

All iOS devices and simulators, Windows 10

  • Last known good version:

N/A

  • IDE:

Visual Studio 16.5.3

Platform Target Frameworks:

  • iOS: 13.4.1
  • Android: Working / 9.0 Pie
  • UWP: 1809 / 17763
  • Nuget Packages:
  • Xamarin Forms 4.5.0.617
  • Xamarin.Essentials 1.5.2

Screenshots

N/A

Reproduction Link

N/A

Workaround

  1. use OnPlatform in ResourceDictionary
    <OnPlatform x:Key="Material" x:TypeArguments="x:String">
        <On Platform="iOS" Value="Material Design Icons" />
        <On Platform="Android" Value="Material" />
        <On Platform="UWP" Value="Material Design Icons" />
    </OnPlatform>
  1. and then for FontFamily
        <Image>
            <Image.Source>
                <FontImageSource FontFamily="{DynamicResource Material}" Glyph="&#x000f0004;" />
            </Image.Source>
        </Image>

But on iOS i needed to navigate of the page and then back for the correct image source icon to be shown

I also encountered this problem an my solution was as follows:

  1. export font in AssemblyInfo.cs
    [assembly: ExportFont("fontAwesomeIcons.ttf", Alias = "FontAwesomeIcons")]
  2. Use Font ImageSource:

Very important: The font family can be the alias (FontAwesomeIcons) on android, however ios requires that you use the actual font name! This may be different from the font file name! I opened the ttf file and saw the name was "Font Awesome 5 Free Solid". I then had to remove the "Solid" part and it worked!

Life saver! None of the Tutorials described this well. So Material IO had changed the Font Name (which can be seen if you open the ttf file). Mine was: "Material Icons". Not "Material Design Icons", not "Material", not the filename. So Steps are:

  1. Info.plist
<key>UIAppFonts</key>
    <array>
      <string>materialDesignIconsIO.ttf</string> <-- file name
   </array>
  1. App.xaml
<OnPlatform x:TypeArguments="x:String" x:Key="IconFontMaterialDesignIO">
<OnPlatform.Android>materialDesignIconsIO.ttf#materialDesignIconsIO</OnPlatform.Android>
<OnPlatform.iOS>Material Icons</OnPlatform.iOS> <-- font name
</OnPlatform>
  1. Usage XAML
    <Label Text="&#xe001;" FontFamily="{StaticResource IconFontMaterialDesignIO}" />

  2. Usage Code (e.g. ViewModel)

ViewModel

public string Icon { get; set; }
Icon = "\ue439";

UI:
<Label Text="{Binding Icon}" FontFamily="{DynamicResource IconFontMaterialDesignIO}"

Tip: Use IconFont2Code to create constants to easy leverage your icon fonts!
https://andreinitescu.github.io/IconFont2Code/

Tip2: Question mark means that there is no found icon. So you have some error in loading your icon font or the spefic icon does not exists.

@jamesmontemagno Maybe you could update your tutorial and specify the filename/icon fontname iOS problematic a little bit. That could save much time because your tutorial is perfect besides this little hint!

I actually put that in my blog: https://montemagno.com/using-font-icons-in-xamarin-forms-goodbye-images-hello-fonts/ and is documented.

Although now with the new font system you shouldn't have to do that at all. I use font awesome with no issues at all.

All i do is this:

[assembly: ExportFont("fa-regular-400.ttf", Alias = "FA-R")]
[assembly: ExportFont("fa-solid-900.ttf", Alias = "FA-S")]
[assembly: ExportFont("fa-brands-400.ttf", Alias = "FA-B")]

@jamesmontemagno ,
Did you experienced some problem regarding Flyoutmenu and FontImageSource? Mine font-awesome icons are working on a regular page, but in my appshell.xaml they dont? Im using the new way of renderering fonts through AssemblyInfo as you mentioned it above (as embedded resource)
example code:

    <ShellContent Route="Items"
                      Title="Items"
                      ContentTemplate="{DataTemplate postlogin:SettingsPage}" >
        <ShellContent.Icon>
            <FontImageSource
                FontFamily="FA-R"
                Glyph="&#xf3c5;"
                Color="Blue"
                Size="24">
            </FontImageSource>
        </ShellContent.Icon>
    </ShellContent>

Mine work well. What version of Xamarin.Forms are you using?

@jamesmontemagno Im using xf 4.7.0.968
I have this menu:

    <FlyoutItem Title="First" Route="postlogin" FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:MapPage}" Title="{Binding [MenuMap].Value, Mode=OneWay, Source={x:Static helper:ResourceLoader.Instance}}" />
    </FlyoutItem>
    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:FiltersPage}" Title="{Binding [MenuFilters].Value, Mode=OneWay, Source={x:Static helper:ResourceLoader.Instance}}" />
    </FlyoutItem>
    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:FavoritesPage}" Title="{Binding [MenuFavorites].Value, Mode=OneWay, Source={x:Static helper:ResourceLoader.Instance}}" />
    </FlyoutItem>
    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:SearchPage}" Title="{Binding [MenuSearch].Value, Mode=OneWay, Source={x:Static helper:ResourceLoader.Instance}}" />
    </FlyoutItem>
    <FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:SettingsPage}" Title="{Binding [MenuSettings].Value, Mode=OneWay, Source={x:Static helper:ResourceLoader.Instance}}" />
    </FlyoutItem>

So, I found that are two props for ShellContent - Icon and FlyoutIcon. Maybe I need to try it with FlyoutIcon?

Updated:
So I tested and It adds just a rectangle like this:
https://i.imgur.com/q2eEGVr.png
and this is the code for the TestItem1:

    <FlyoutItem Title="First" Route="postlogin" FlyoutDisplayOptions="AsMultipleItems">
        <ShellContent ContentTemplate="{DataTemplate postlogin:MapPage}" Title="TestItem1">
            <ShellContent.Icon>
                <FontImageSource Glyph="{StaticResource IconPin}" FontFamily="FA-R" />
            </ShellContent.Icon>
        </ShellContent>
    </FlyoutItem>

Thanks

That means your font is not added correctly. Make sure it is an embedded resource -> https://github.com/jamesmontemagno/app-ac-islandtracker/blob/master/TurnipTracker/TurnipTracker.csproj#L33-L38 and that you added the exports -> https://github.com/jamesmontemagno/app-ac-islandtracker/blob/master/TurnipTracker/AssemblyInfo.cs#L6-L8

I see an error message on Android when trying to use the material icon font with FontImageSource for a tab icon.

The same font displays fine when used on a Button in the same project.

Using Forms 4.7.0.1239 on netstandard 2.0 on Android API 26 simulator.
Also tried with Forms 4.7.0.1260.
Also tried latests Forms prerelease, where the font won't display in the button anymore. still does not display on the tab icon.

08-06 16:52:39.799 E/FontFamily( 6025): Error mapping font file /data/user/0/com.zzz/cache/material_icons_regular.ttf [0:] Image loading: Image load failed: Java.Lang.RuntimeException: Font not found /data/user/0/com.zzz/cache/material_icons_regular.ttf at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0006e] in <bf671abdfa384ce99d758b134b9dd5bf>:0 at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) [0x00018] in <bf671abdfa384ce99d758b134b9dd5bf>:0 at Android.Graphics.Typeface.CreateFromFile (System.String path) [0x00029] in <a522ecdee49144d0b8411a1cab7b9ada>:0 at Xamarin.Forms.Platform.Android.FontExtensions.TryGetFromAssets (System.String fontName) [0x00016] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\FontExtensions.cs:65 at Xamarin.Forms.Platform.Android.FontExtensions.ToTypeFace (System.String fontfamily, Xamarin.Forms.FontAttributes attr) [0x0000c] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\FontExtensions.cs:47 at Xamarin.Forms.Platform.Android.FontImageSourceHandler.LoadImageAsync (Xamarin.Forms.ImageSource imagesource, Android.Content.Context context, System.Threading.CancellationToken cancelationToken) [0x0006f] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\FontImageSourceHandler.cs:29 at Xamarin.Forms.Platform.Android.ResourceManager.GetFormsBitmapAsync (Android.Content.Context context, Xamarin.Forms.ImageSource imageSource, System.Threading.CancellationToken cancellationToken) [0x00045] in D:\a\1\s\Xamarin.Forms.Platform.Android\ResourceManager.cs:148 --- End of managed Java.Lang.RuntimeException stack trace ---

Was this page helpful?
0 / 5 - 0 ratings