Xamarin Forms 如何设置More按钮内标签页的背景色
Xamarin.Forms Shell More页面样式不生效问题
问题场景
基于Xamarin.Forms.Shell开发应用实现布局与导航功能时,TabBar中添加的标签数量超过5个后,Android、iOS平台会原生生成More按钮收纳超出的标签。在XAML中配置Shell.BackgroundColor、Shell.TabBarBackgroundColor等自定义颜色属性后,More按钮展开的收纳页面没有应用自定义样式。
对应App Shell的XAML代码如下:
<Shell.Resources> <ResourceDictionary> <Style x:Key="BaseStyle" TargetType="Element"> <Setter Property="Shell.BackgroundColor" Value="{x:Static core:Colors.Background}" /> <Setter Property="Shell.ForegroundColor" Value="White" /> <Setter Property="Shell.TabBarBackgroundColor" Value="{x:Static core:Colors.Background}" /> <Setter Property="Shell.TabBarTitleColor" Value="{x:Static core:Colors.Selection}" /> <Setter Property="Shell.TabBarUnselectedColor" Value="White" /> </Style> </ResourceDictionary> </Shell.Resources> <ShellItem Route="Home"> <ShellContent ContentTemplate="{DataTemplate core:HomePage}"/> </ShellItem> <TabBar Route="Tabs" Style="{x:StaticResource BaseStyle}"> <Tab Route="TabSearch" Icon="ic_list_white" Title="Search"> <ShellContent ContentTemplate="{DataTemplate core:SearchPage}"/> </Tab> <Tab Icon="ic_filter_list_white" Title="Filter"> <ShellContent ContentTemplate="{DataTemplate core:FilterPage}"/> </Tab> <Tab Icon="ic_star_white" Title="Favourites"> <ShellContent ContentTemplate="{DataTemplate core:FavouritesPage}"/> </Tab> <Tab Icon="ic_remove_red_eye_white" Title="Seen"> <ShellContent ContentTemplate="{DataTemplate core:SeenPage}"/> </Tab> <Tab Icon="ic_shopping_cart_white" Title="{x:Static resources:Strings.MAINPAGE_MENU_PURCHASE_PACKAGES}"> <ShellContent ContentTemplate="{DataTemplate core:PackagePurchasePage}"/> </Tab> <Tab Icon="ic_sync_white" Title="{x:Static resources:Strings.MAINPAGE_MENU_RESTORE_PURCHASES}" > <ShellContent ContentTemplate="{DataTemplate core:RestorePurchasePage}"/> </Tab> <Tab Icon="ic_settings_white" Title="{x:Static resources:Strings.MAINPAGE_MENU_SETTINGS}" > <ShellContent ContentTemplate="{DataTemplate core:SettingsPage}"/> </Tab> <Tab Icon="ic_help_white" Title="{x:Static resources:Strings.MAINPAGE_MENU_ABOUT}" > <ShellContent ContentTemplate="{DataTemplate views:AboutShell }"/> </Tab> </TabBar>
效果对比:
- 已应用自定义样式的TabBar:

- More按钮展开的收纳页未应用自定义样式:

目标:让More按钮展开页面的样式与TabBar已配置的自定义样式完全统一。
解决方案
Shell的More页面由各平台原生控件渲染,不会自动继承Shell层定义的TabBar颜色属性,需要通过平台自定义渲染器单独配置样式。
Android平台实现
在Android项目中添加自定义Shell渲染器,重写More页面相关的样式回调:
using Android.Content; using Android.Widget; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; // 替换为你自己的Android项目命名空间 using YourAppName.Droid; [assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))] namespace YourAppName.Droid { public class CustomShellRenderer : ShellRenderer { public CustomShellRenderer(Context context) : base(context) { } protected override IShellMoreViewAppearanceTracker CreateMoreViewAppearanceTracker(ShellItem shellItem) { return new CustomMoreViewAppearance(); } } public class CustomMoreViewAppearance : IShellMoreViewAppearanceTracker { public void ResetAppearance(MoreView view, ShellMoreViewAppearance appearance) { // 设置More页面整体背景色,复用你定义的全局背景色 view.SetBackgroundColor(YourAppName.Colors.Background.ToAndroid()); // 修改列表项文字的选中/未选中颜色 var listView = view.FindViewById<ListView>(Android.Resource.Id.List); listView.Adapter = new ColorConfiguredListAdapter( listView.Adapter, Color.White.ToAndroid(), YourAppName.Colors.Selection.ToAndroid() ); // 修改顶部导航栏背景色 if (view.Parent is ViewGroup parent) { for (int i = 0; i < parent.ChildCount; i++) { var child = parent.GetChildAt(i); if (child is FrameLayout navBar) { navBar.SetBackgroundColor(YourAppName.Colors.Background.ToAndroid()); break; } } } } public void SetAppearance(MoreView view, ShellMoreViewAppearance appearance) { ResetAppearance(view, appearance); } } internal class ColorConfiguredListAdapter : BaseAdapter { private readonly IListAdapter _innerAdapter; private readonly Android.Graphics.Color _normalTextColor; private readonly Android.Graphics.Color _selectedTextColor; public ColorConfiguredListAdapter(IListAdapter innerAdapter, Android.Graphics.Color normalTextColor, Android.Graphics.Color selectedTextColor) { _innerAdapter = innerAdapter; _normalTextColor = normalTextColor; _selectedTextColor = selectedTextColor; } public override int Count => _innerAdapter.Count; public override Java.Lang.Object GetItem(int position) => _innerAdapter.GetItem(position); public override long GetItemId(int position) => _innerAdapter.GetItemId(position); public override View GetView(int position, View convertView, ViewGroup parent) { var itemView = _innerAdapter.GetView(position, convertView, parent); if (itemView is CheckedTextView textView) { textView.SetTextColor(new ColorStateList( new[] { new[] { -Android.Resource.Attribute.StateChecked }, new[] { Android.Resource.Attribute.StateChecked } }, new[] { _normalTextColor, _selectedTextColor } )); } return itemView; } } }
iOS平台实现
在iOS项目中添加自定义Shell渲染器,修改More页面对应的导航控制器和列表样式:
using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; // 替换为你自己的iOS项目命名空间 using YourAppName.iOS; [assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))] namespace YourAppName.iOS { public class CustomShellRenderer : ShellRenderer { public override void ViewDidLayoutSubviews() { base.ViewDidLayoutSubviews(); // 匹配到More页面的导航控制器 if (SelectedViewController is UINavigationController nav && nav.TopViewController is UITableViewController morePage) { // 配置列表背景色 morePage.TableView.BackgroundColor = YourAppName.Colors.Background.ToUIColor(); // 配置导航栏样式 nav.NavigationBar.BarTintColor = YourAppName.Colors.Background.ToUIColor(); nav.NavigationBar.TintColor = UIColor.White; nav.NavigationBar.TitleTextAttributes = new UIStringAttributes { ForegroundColor = UIColor.White }; } } protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker() { return new CustomTabBarAppearance(); } } public class CustomTabBarAppearance : ShellTabBarAppearanceTracker { public override void UpdateLayout(UITabBarController controller) { base.UpdateLayout(controller); // 初始化时配置More页面导航栏样式 var moreNav = controller.MoreNavigationController; moreNav.NavigationBar.BarTintColor = YourAppName.Colors.Background.ToUIColor(); moreNav.NavigationBar.TintColor = UIColor.White; moreNav.NavigationBar.TitleTextAttributes = new UIStringAttributes { ForegroundColor = UIColor.White }; } } }
配置说明
- 将代码中
YourAppName替换为你项目的实际根命名空间,颜色直接复用XAML中定义的全局静态颜色资源即可,保证全局样式统一。 - 如果需要适配深色模式,在平台主题切换回调中重新执行样式设置逻辑即可。
内容的提问来源于stack exchange,提问作者Beatriz Pinheiro
相关产品推荐
相关产品推荐

