我有一个带有消息图标的底部选项卡栏,它显示带有消息的选项卡(ShellContent)页面。现在,如何在选项卡栏图标顶部动态显示数字,示例用例:当用户有 2 条新消息时,在消息图标上显示数字 2。我只有如下基本选项卡项目,请建议如何在其上动态显示数字。我也遵循MVVM架构。
<Tab Title="Inbox" x:Name="messages"
Icon="message.svg">
<ShellContent ContentTemplate="{DataTemplate views:MessagesPage}" Route="messages"/>
</Tab>
您可以尝试使用适用于 Android 和 iOS 的自定义平台特定 shell 处理程序来实现此目的。
请参考以下代码:
在安卓上:
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;
}
}
}
在 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;
}
}
}
在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();
}
}
参考:https://github.com/dotnet/maui/issues/8305#issuecomment-1742160046