Cloud Stack Ninja

I want to show icons and text on my Android TabbedPage tabs in my Xamarin application, and I want them to be FontAwesome glyphs rather than png files.

My TabbedPage is defined in code, and I originally set the IconImageSource for the child pages in their constructors. In iOS, that's all I seem to need to do for png files to show up, but in Android that didn't work (though I think it should have, no idea why it didn't) so I seem to need a custom renderer even for the pngs. This renderer works for pngs if I add an "IconName" field to each of my ContentPage classes and set its value to the name of the png file (without the .png extension):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Internal;
using Android.Support.Design.Widget;
using Android.Support.V4.Content;
using Android.Views;
using Android.Widget;
using Origami.MobileForms.Droid.Renderers;
using Origami.MobileForms.Pages;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;

[assembly: ExportRenderer(typeof(FormTabbedPage), typeof(ExtendedTabbedPageRenderer))]
namespace Origami.MobileForms.Droid.Renderers
{
    public class ExtendedTabbedPageRenderer : TabbedRenderer
    {
        public ExtendedTabbedPageRenderer(Context context) : base(context) { }

        protected override void DispatchDraw(global::Android.Graphics.Canvas canvas)
        {
            base.DispatchDraw(canvas);

            SetTabIcons();
        }

        private void SetTabIcons()
        {

            var element = this.Element;
            if (null == element)
            {
                return;
            }

            Activity activity = this.Context as Activity;
            if ((null != activity && null != activity.ActionBar && activity.ActionBar.TabCount > 0))
            {
                for (int i = 0; i < element.Children.Count; i += 1)
                {
                    Android.App.ActionBar.Tab tab = activity.ActionBar.GetTabAt(i);
                    var page = element.Children[i];
                    if ((null != tab) && (null != page) && (null != page.IconImageSource))
                    {
                        var customImagePage = page as ICustomImagePage;
                        if(customImagePage != null)
                        {
                            var resourceId = Resources.GetIdentifier(customImagePage.IconName.ToLower(), "drawable", Context.PackageName);
                            tab.SetIcon(resourceId);
                        }
                    }
                }
            }
        }
    }
}

I'm trying to figure out how to use FontAwesome icons instead of .png files here. I did figure out how to use a FontAwesome icon as the IconImageSource in my ContentPage:

this.IconImageSource = new FontImageSource { FontFamily = "fa-solid", Size = 30,  Glyph= "\uf15c", Color = Color.Red }; 

with this attribute added in my shared project over the namespace of the App class:

[assembly: ExportFont("fa-solid-900.ttf", Alias = "fa-solid")]

However, the SetIcon method that I'm using in the TabbedRenderer override only accepts a ResourceID or a Drawable as a parameter, and I'm not sure how to generate either one of those from a FontAwesome icon. I tried using the TextDrawable NuGet package by eddydn as follows in my custom renderer, which compiles and runs, but no icon shows up:

private void SetTabIcons()
{

    var element = this.Element;
    if (null == element)
    {
        return;
    }

    Activity activity = this.Context as Activity;
    if ((null != activity && null != activity.ActionBar && activity.ActionBar.TabCount > 0))
    {
        for (int i = 0; i < element.Children.Count; i += 1)
        {
            var page = element.Children[i];
            if ((null != tab) && (null != page) && (null != page.IconImageSource))
            {
                var customImagePage = page as ICustomImagePage;
                if(customImagePage != null)
                {
                    Typeface font = Typeface.Create("fa-solid", TypefaceStyle.Normal);
                    TextDrawable icon = new TextDrawable.Builder().BeginConfig().TextColor(Android.Graphics.Color.Red).UseFont(font)
                        .FontSize(30).EndConfig()
                        .BuildRect("\uf15c", Android.Graphics.Color.Red);
                    tab.SetIcon(icon);
                }
            }
        }
    }
}

I have also tried another way to get the drawable object for the SetIcon call, using the IconDrawable class defined here: Use an Icon Font in Xamarin Forms TabBar (and modifying the line in IconDrawable that sets the Typeface to use Create or CreateFromAsset based on how I imported FontAwesome) like this:

var drawable = new IconDrawable(this.Context, "\uf15c";", "fa-solid").Color(Xamarin.Forms.Color.Red.ToAndroid()).SizeDp(30);

The way I described above of including FontAwesome in a solution (adding to the shared project and adding an attribute outside the namespace to activate it) is the newer way of referencing FontAwesome. I know it works since the iOS project shows the icons, but I'm not 100% sure that referencing it from the Droid project's TabbedRenderer when it's included via the shared project is okay

I have also tried the older way of referencing FontAwesome: add the file under the Assets folder. In my TabbedRenderer code above that uses Typeface.Create, switch to use Typeface.CreateFromAsset like this:

_paint.SetTypeface(Typeface.CreateFromAsset(context.Assets, $"{fontFacePath}.ttf"));  

I'm sure that way should work for the TabbedRenderer, but I don't know a simple way to test to just be sure that the load of FontAwesome in the project is working at all there.

Thank you in advance for any assistance you may be able to offer!



Read more here: https://stackoverflow.com/questions/64392366/xamarin-android-tabbedpage-show-fontawesome-icon-on-tab

Content Attribution

This content was originally published by user756366 at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: