Xamarin Android TabbedPage 在选项卡上显示 FontAwesome 图标

Xamarin Android TabbedPage show FontAwesome icon on tab

我想在 Xamarin 应用程序的 Android TabbedPage 选项卡上显示图标和文本,我希望它们是 FontAwesome 字形而不是 png 文件。

我的 TabbedPage 是在代码中定义的,我最初在其构造函数中为子页面设置了 IconImageSource。在 iOS 中,这就是我似乎需要做的所有工作才能显示 png 文件,但在 Android 中这不起作用(虽然我认为它应该有,但不知道为什么没有)所以即使是 png,我似乎也需要一个自定义渲染器。如果我向每个 ContentPage classes 添加一个“IconName”字段并将其值设置为 png 文件的名称(不带 .png 扩展名),此渲染器适用于 png:

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);
                        }
                    }
                }
            }
        }
    }
}

我想弄清楚如何在这里使用 FontAwesome 图标而不是 .png 文件。我确实弄清楚了如何在我的 ContentPage 中使用 FontAwesome 图标作为 IconImageSource:

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

在我的共享项目中通过应用程序的命名空间添加此属性 class:

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

但是,我在 TabbedRenderer 覆盖中使用的 SetIcon 方法只接受 ResourceID 或 Drawable 作为参数,我不确定如何从 FontAwesome 图标生成其中任何一个。我尝试在我的自定义渲染器中使用 eddydn 的 TextDrawable NuGet 包,编译并运行,但没有显示图标:

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);
                }
            }
        }
    }
}

我还尝试了另一种方法来获取 SetIcon 调用的可绘制对象,使用 IconDrawable class 定义 here(并修改 IconDrawable 中设置字体以使用 Create 或CreateFromAsset 基于我导入 FontAwesome 的方式)像这样:

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

提前感谢您提供的任何帮助!

我几乎完成了上面的最后一次尝试 - 问题是我试图将 IconDrawable 设置为:

Typeface.Create(fontFacePath, TypefaceStyle.Normal);

我希望使用我包含在我的共享项目中的文件创建字体,并通过属性添加到该项目的代码中,但可能以更新的方式包含它们不会使字体在 Droid 中可访问项目...无论如何,当我改为使用将 FontAwesome 添加到项目的旧方法时 - 在 Droid 项目的 Assets 文件夹下添加 FontAwesome(.otf 或 .ttf)并调用

Typeface.CreateFromAsset(context.Assets, $"{fontFacePath}.otf") 

(或 .ttf)获取字体 - 效果很好。