PAYATHON 2026

如何从 ContentPage 更改 MAUI TabBar 背景颜色?

技术老齐

结论

可以通过 Shell.Current 获取当前运行的 AppShell 实例。要修改 TabBar 的背景色,直接设置 Shell 的附加属性即可,不需要使用 ViewModel:

if (Shell.Current is AppShell appShell)
{
    Shell.SetTabBarBackgroundColor(appShell, Colors.Purple);
}

调用 AppShell.SetTabBarColor(...) 会报错,因为 AppShell 是类型名,SetTabBarColor 则是实例方法,需要通过实际的 AppShell 对象调用。

在 AppShell 中封装方法

可以在 AppShell.xaml.cs 中添加一个实例方法:

namespace SleepDiary;

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
    }

    public void SetTabBarColor(Color color)
    {
        Shell.SetTabBarBackgroundColor(this, color);
    }
}

在任意 ContentPage 中获取当前 Shell 实例后调用该方法:

private void OnChangeColorClicked(object sender, EventArgs e)
{
    if (Shell.Current is AppShell appShell)
    {
        appShell.SetTabBarColor(Colors.Purple);
    }
}

这里的 this 位于 AppShell 的实例方法中,表示当前的 AppShell 对象,可以传给 SetTabBarBackgroundColor。

如果不打算封装方法,也可以直接在页面中设置颜色:

private void OnChangeColorClicked(object sender, EventArgs e)
{
    if (Shell.Current is AppShell appShell)
    {
        Shell.SetTabBarBackgroundColor(appShell, Colors.Purple);
    }
}

初始颜色可以直接写在 XAML 中:

<Shell
    x:Class="SleepDiary.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    Shell.FlyoutBehavior="Disabled"
    Shell.TabBarTitleColor="White"
    Shell.TabBarUnselectedColor="LightGray"
    Shell.TabBarBackgroundColor="Blue">

使用 buttoncolor 属性

如果 buttoncolor 是定义在 AppShell 中的 BindableProperty,修改时同样需要使用当前的 AppShell 实例。按照 C# 的命名习惯,可以将属性名改为 ButtonColor:

namespace SleepDiary;

public partial class AppShell : Shell
{
    public static readonly BindableProperty ButtonColorProperty =
        BindableProperty.Create(
            nameof(ButtonColor),
            typeof(Color),
            typeof(AppShell),
            Colors.Blue);

    public Color ButtonColor
    {
        get => (Color)GetValue(ButtonColorProperty);
        set => SetValue(ButtonColorProperty, value);
    }

    public AppShell()
    {
        InitializeComponent();
    }
}

在 XAML 中明确指定绑定来源,让绑定读取 AppShell 自身的属性,不受页面 BindingContext 的影响:

<Shell
    x:Class="SleepDiary.AppShell"
    x:Name="RootShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    Shell.FlyoutBehavior="Disabled"
    Shell.TabBarTitleColor="White"
    Shell.TabBarUnselectedColor="LightGray"
    Shell.TabBarBackgroundColor="{Binding ButtonColor, Source={x:Reference RootShell}}">

然后在 ContentPage 中修改该属性:

private void OnChangeColorClicked(object sender, EventArgs e)
{
    if (Shell.Current is AppShell appShell)
    {
        appShell.ButtonColor = Colors.Purple;
    }
}

绑定路径需要指向公开的 CLR 属性,例如 ButtonColor,只定义字段无法完成绑定。属性名的大小写也必须与 XAML 中的绑定路径一致。

static 写法为什么不可行

以下代码定义的是静态方法:

public static void SetTabBarColor(Color color)
{
}

静态方法不属于任何具体的 AppShell 实例,所以方法中没有可用的 this,也无法直接访问实例属性 ButtonColor。

下面的方法则属于实例:

public void SetTabBarColor(Color color)
{
    ButtonColor = color;
}

因此,不能通过类型名这样调用:

AppShell.SetTabBarColor(Colors.Purple);

需要先获取实例,再调用方法:

if (Shell.Current is AppShell appShell)
{
    appShell.SetTabBarColor(Colors.Purple);
}

只修改 TabBar 颜色时,直接使用 Shell.SetTabBarBackgroundColor 更省事。如果按钮颜色和 TabBar 颜色共用一个属性,可以保留 ButtonColor 和对应的 XAML 绑定。颜色修改通常需要在 UI 线程中执行,而按钮点击事件本身就在 UI 线程中。

备注:内容仅供参考。