如何从 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 线程中。
备注:内容仅供参考。
