Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change Tab title font for TabBar in .NET MAUI

In my AppShell.xaml I have the following code for a TabBar. I can't seem to find a property or anything that allows me to change the font (and font size etc.) of the title.

<TabBar x:Name="TabBar">
    <Tab x:Name="HomePage" Title="Home" Icon="tab_home.png">
        <ShellContent ContentTemplate="{DataTemplate local:MainPage}" Route="MainPage" />
    </Tab>
</TabBar>

Even in Resources/Styles/Styles.xaml I don't see a property in the shell or tabbedpage for font family.

like image 509
Cody Avatar asked Oct 23 '25 16:10

Cody


2 Answers

You can try to set Font Icons in Shell Tabs.

Please refer to the following code:

1.add the font you wanted.

public static class MauiProgram 
{
      public static MauiApp CreateMauiApp()
      {
            var builder = MauiApp.CreateBuilder();
            builder
                  .UseMauiApp<App>()
                  .ConfigureFonts(fonts =>
                  {
                        fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                        fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                // add your font here
                fonts.AddFont("icomoon.ttf", "FA");
            }); 

            return builder.Build();
      }
}

2.Usage:

<TabBar> 
    <ShellContent Title="About" Icon="{FontImage FontFamily=FA , Glyph=&#xe922;}" Route="AboutPage" ContentTemplate="{DataTemplate local:CatsPage}" />
    <ShellContent Title="Items" Icon="{FontImage FontFamily=FA , Glyph=&#xe910;}" ContentTemplate="{DataTemplate local:MainPage}" />
</TabBar>

Note:

Please add the font into folder Fonts and make sure the build action is MauiFont.

like image 194
Jessie Zhang -MSFT Avatar answered Oct 26 '25 06:10

Jessie Zhang -MSFT


Based on the answer in how can i remove or hide the text of tabs in TabBar .NET MAUI?

You can change both the font and the font size of the title in the TabBar.

In Android:

You need to add a custom renderer in Platforms/Android/Renderers

[assembly: ExportRenderer(typeof(Shell), typeof(CustomShellRenderer))]
namespace YourApp.Platforms.Android.Renderers;
    
public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context) : base(context)
    {
    }
    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new CustomBottomNavViewAppearanceTracker(this, shellItem);
    }
}
public class CustomBottomNavViewAppearanceTracker : ShellBottomNavViewAppearanceTracker
{
    public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        base.SetAppearance(bottomView, appearance);

            // Set custom font with any font file name you need as registered in MauiProgram.cs builder.ConfigureFonts()
            var font = Typeface.CreateFromAsset(ShellContext.AndroidContext.Assets, "FONTFILENAME.ttf");
            // replace FONTSIZE with you needed font size
            var spanFace = new CustomTypefaceSpan("", font, FONTSIZE);
            // if you need you can change the direction of the bottom navigation view
            bottomView.LayoutDirection = LayoutDirection.Rtl;
            var menu = bottomView.Menu;
            for (var i = 0; i < menu.Size(); i++)
            {
                // Set custom label with custom fonts
                var menuItem = menu.GetItem(i);
                if (menuItem == null) continue;
                var spannableString = new SpannableString(menuItem.TitleCondensedFormatted);
                spannableString.SetSpan(spanFace, 0, spannableString.Length(), SpanTypes.ExclusiveExclusive);
                menuItem.SetTitle(spannableString);
            }
     
    }
    public CustomBottomNavViewAppearanceTracker(IShellContext shellContext, ShellItem shellItem) : base(shellContext, shellItem)
    {
        ShellContext = shellContext;
    }
    private IShellContext ShellContext { get; }
  }
}
public class CustomTypefaceSpan : TypefaceSpan
{
    private float? FontSize { get; }
    private readonly Typeface _typeface;
    public CustomTypefaceSpan(string family, Typeface typeface, float? fontSize = null) : base(family)
    {
        FontSize = fontSize;
        _typeface = typeface;
    }
    public override void UpdateDrawState(TextPaint ds)
    {
        ApplyCustomTypeFace(ds, _typeface);
    }
    public override void UpdateMeasureState(TextPaint paint)
    {
        ApplyCustomTypeFace(paint, _typeface);
    }
    private void ApplyCustomTypeFace(Paint paint, Typeface tf)
    {
        if (FontSize != null && FontSize != 0)
            paint.TextSize = FontSize.Value;
        paint.SetTypeface(tf);
    }
}

For iOS: You need to add a custom renderer in Platforms/iOS/Renderers

public class CustomShellRenderer : ShellRenderer
{
    protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
    {
        return new CustomTabBarAppearance(Shell);
    }
    protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
    {
        return new CustomSectionRenderer(this);
    }
}
public class CustomSectionRenderer(IShellContext context) : ShellSectionRenderer(context);

public class CustomTabBarAppearance : IShellTabBarAppearanceTracker
{
    private Shell Shell { get; }
    private CustomTabBar? CustomTabBar => Shell.CurrentItem as CustomTabBar;
    public CustomTabBarAppearance(Shell shell)
    {
        Shell = shell;
    }
    public void Dispose()
    {
    }
    public void ResetAppearance(UITabBarController controller)
    {
    }
    public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
    {
        var tabBar = controller.TabBar;
        UpdateTabBar(tabBar);

    }
    [System.Runtime.Versioning.SupportedOSPlatform("ios")]
    private void UpdateTabBar(UITabBar? tabBar)
    {
        if (tabBar == null) return;
        var fontFamily = CustomTabBar?.FontFamily;
        var fontSize = CustomTabBar?.FontSize ?? 0;
        var font = UIFont.FromName(fontFamily, fontSize);


        if (OperatingSystem.IsIOSVersionAtLeast(9))
        {
            tabBar.SemanticContentAttribute =
                LangUtilities.IsRtl ?
                    UISemanticContentAttribute.ForceRightToLeft
                    : UISemanticContentAttribute.ForceLeftToRight;
        }
        if (OperatingSystem.IsIOSVersionAtLeast(13)&& UIDevice.CurrentDevice.CheckSystemVersion(13, 0) && DeviceInfo.Platform ==DevicePlatform.iOS)
        {
          #if IOS13_0_OR_GREATER

            void UpdateAppearance(UITabBarItemStateAppearance appearance, bool changeToWhite=true)
            {
                
                appearance.TitleTextAttributes = new UIStringAttributes(appearance.TitleTextAttributes.Dictionary)
                {
                    Font = font,
                    ForegroundColor = Application.Current?.RequestedTheme switch
                    {
                        

                        AppTheme.Dark => changeToWhite? UIColor.White:appearance.TitleTextAttributes.ForegroundColor,
                        
                        _ => appearance.TitleTextAttributes.ForegroundColor
                    } ?? appearance.TitleTextAttributes.ForegroundColor
                };
               
            }

            var barAppearance = new UITabBarAppearance(tabBar.StandardAppearance);
            var layoutAppearance = barAppearance.StackedLayoutAppearance;
            UpdateAppearance( layoutAppearance.Normal);
            UpdateAppearance(layoutAppearance.Disabled);
            UpdateAppearance(layoutAppearance.Selected,false);
            UpdateAppearance(layoutAppearance.Focused);
            barAppearance.ShadowColor = null;
            barAppearance.ShadowImage = null;
            tabBar.StandardAppearance = barAppearance;
          #endif

            if (OperatingSystem.IsIOSVersionAtLeast(15))
                tabBar.ScrollEdgeAppearance = barAppearance;
        }
        else
        {
            if (tabBar.Items == null) return;
            foreach (var uiTabBarItem in tabBar.Items)
            {
                var states = new[] { UIControlState.Normal, UIControlState.Selected };
                foreach (var state in states)
                {
                    var textAttributes = uiTabBarItem.GetTitleTextAttributes(state);
                    textAttributes.Font = font;
                    uiTabBarItem.SetTitleTextAttributes(textAttributes, state);
                }
            }
        }
    }
    public void UpdateLayout(UITabBarController controller)
    {
        var tabBar = controller.TabBar;
        var height = CustomTabBar?.MinHeight;
        if (height != null)
        {
            
            if (tabBar.Frame.Height != height)
            {
                tabBar.Frame = new CGRect(tabBar.Frame.X, tabBar.Frame.Y + (tabBar.Frame.Height - height.Value), tabBar.Frame.Width, height.Value);
            }
        }

        tabBar.ClipsToBounds = false;
    }
}

Also create CustomTabBar.cs

public class CustomTabBar : TabBar
{
public CustomTabBar()
{
    DescendantAdded += CustomTabBar_DescendantAdded;
}

private void CustomTabBar_DescendantAdded(object? sender, ElementEventArgs e)
{
    if (e.Element is ShellContent shellContent)
    {
        var data = shellContent.ContentTemplate as IDataTemplateController;
        shellContent.Route = data.IdString.Split('.').Last().ToLower();
    }
}

public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(
    nameof(FontSize), typeof(float), typeof(CustomTabBar));
public float FontSize
{
    get => (float)GetValue(FontSizeProperty);
    set => SetValue(FontSizeProperty, value);
}

public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(
    nameof(FontFamily), typeof(string), typeof(CustomTabBar));

public static readonly BindableProperty MinHeightProperty = BindableProperty.Create(
    nameof(MinHeight), typeof(int?), typeof(CustomTabBar));

public int? MinHeight
{
    get => (int?)GetValue(MinHeightProperty);
    set => SetValue(MinHeightProperty, value);
}
public string FontFamily
{
    get => (string)GetValue(FontFamilyProperty);
    set => SetValue(FontFamilyProperty, value);
}

}

In MauiProgram.cs add to builder object that call

 .ConfigureMauiHandlers(handlers =>
            {
#if ANDROID
                handlers.AddHandler(typeof(Shell), typeof(Platforms.Android.Renderers.CustomShellRenderer));

#elif IOS
                handlers.AddHandler(typeof(Shell), typeof(Platforms.iOS.Renderers.CustomShellRenderer));
#endif
            });
like image 40
Ahmed Samy Moursi Hashwa Avatar answered Oct 26 '25 05:10

Ahmed Samy Moursi Hashwa