user1066231
user1066231

Reputation: 593

how to dynamically add numbers over Tab icons. .net maui

I have a bottom TabBar with a Message Icon, that shows a tab(ShellContent) a page with Messages. Now how can I dynamically show numbers on top of the Tabbar icon, example usecase: Display number 2 over Message icon when user has 2 new messages. I just have basic Tab item as below, please suggest how can I dynamically display number on it. I also follow MVVM architecture.

<Tab Title="Inbox" x:Name="messages" 
        Icon="message.svg">
        <ShellContent ContentTemplate="{DataTemplate views:MessagesPage}" Route="messages"/>
    </Tab>

Upvotes: 0

Views: 344

Answers (1)

Jessie Zhang -MSFT
Jessie Zhang -MSFT

Reputation: 13879

You can try to achieve this with custom platform specific shell handlers for Android and iOS.

Please refer to the following code:

On android:

namespace ShellTabbarBadgeMAUI
{
    public class TabbarBadgeRenderer : ShellRenderer
    {
        protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
        {
            //return base.CreateBottomNavViewAppearanceTracker(shellItem);
            return new BadgeShellBottomNavViewAppearanceTracker(this, shellItem);
        }
    }

    class BadgeShellBottomNavViewAppearanceTracker : ShellBottomNavViewAppearanceTracker
    {
        private BadgeDrawable? badgeDrawable;
        public BadgeShellBottomNavViewAppearanceTracker(IShellContext shellContext, ShellItem shellItem) : base(shellContext, shellItem)
        {
        }
        public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
        {
            base.SetAppearance(bottomView, appearance);

            if (badgeDrawable is null)
            {
                const int cartTabbarItemIndex = 1;

                badgeDrawable = bottomView.GetOrCreateBadge(cartTabbarItemIndex);
                UpdateBadge(0);
                BadgeCounterService.CountChanged += OnCountChanged;
            }
        }
        private void OnCountChanged(object? sender, int newCount)
        {
            UpdateBadge(newCount);
        }
        private void UpdateBadge(int count)
        {
            if(badgeDrawable is not null)
            {
                if (count <= 0)
                {
                    badgeDrawable.SetVisible(false);
                }
                else
                {
                    badgeDrawable.Number = count;
                    badgeDrawable.BackgroundColor = Colors.Red.ToPlatform();
                    badgeDrawable.BadgeTextColor = Colors.White.ToPlatform();
                    badgeDrawable.SetVisible(true);
                }
            }
        }
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            BadgeCounterService.CountChanged -= OnCountChanged;
        }
    }
}

On iOS:

namespace ShellTabbarBadgeMAUI
{
    public class TabbarBadgeRenderer : ShellRenderer
    {
        protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
        {
            //return base.CreateTabBarAppearanceTracker();
            return new BadgeShellTabbarAppearanceTracker();
        }
    }
    class BadgeShellTabbarAppearanceTracker : ShellTabBarAppearanceTracker
    {
        private UITabBarItem? _cartTabbarItem;
        public override void UpdateLayout(UITabBarController controller)
        {
            base.UpdateLayout(controller);

            if (_cartTabbarItem is null)
            {
                const int cartTabbarItemIndex = 1;

                _cartTabbarItem = controller.TabBar.Items?[cartTabbarItemIndex];
                if (_cartTabbarItem is not null)
                {
                    UpdateBadge(0);
                    BadgeCounterService.CountChanged += OnCountChanged;
                }
            }
        }
        private void OnCountChanged(object? sender, int newCount)
        {
            UpdateBadge(newCount);
        }
        private void UpdateBadge(int count)
        {
            if(_cartTabbarItem is not null)
            {
                if(count <= 0)
                {
                    _cartTabbarItem.BadgeValue = null;
                }
                else
                {
                    _cartTabbarItem.BadgeValue = count.ToString();
                    _cartTabbarItem.BadgeColor = Colors.Red.ToPlatform();
                }
            }
        }
        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            BadgeCounterService.CountChanged -= OnCountChanged;
        }
    }
}

In MauiProgram.cs

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");
            })
            .ConfigureMauiHandlers(h=>
            {
#if ANDROID || IOS
                h.AddHandler<Shell, TabbarBadgeRenderer>();
#endif
            });

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }
}

Refer : https://github.com/dotnet/maui/issues/8305#issuecomment-1742160046

Upvotes: 1

Related Questions