Xamarin Forms中如何让ToolbarItem图标正常显示色彩与细节?
问题原因
Android平台原生Toolbar的菜单项(对应Xamarin.Forms的ToolbarItem)默认开启图标色调强制渲染规则,会将所有加载的图标统一覆盖为主题配置的colorControlNormal单色,直接丢失原图标自带的色彩和细节。FlyoutItem对应的原生控件未启用该强制渲染逻辑,因此同一张图标作为Flyout图标时可在Android端正常显示;UWP平台无该默认渲染规则,因此显示正常。
解决方案
方案1:全局修改Android主题,关闭Toolbar图标色调渲染
该方案无需编写自定义渲染逻辑,全局生效,配置成本最低。
打开Android项目路径下的Resources/values/styles.xml,在应用使用的主题节点中新增如下配置:
<style name="MainTheme" parent="MainTheme.Base"> <!-- 保留原有已配置的主题属性,新增以下两项 --> <item name="android:actionBarTheme">@style/CustomActionBarTheme</item> <item name="toolbarStyle">@style/CustomToolbarStyle</item> </style> <style name="CustomActionBarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar"> <item name="colorControlNormal">@android:color/transparent</item> <item name="android:colorControlNormal">@android:color/transparent</item> </style> <style name="CustomToolbarStyle" parent="Widget.AppCompat.Toolbar"> <item name="android:tint">@null</item> <item name="app:tint">@null</item> </style>
如果项目使用Material系列主题,只需将上述自定义style的parent节点替换为对应的Material主题父类即可,属性配置逻辑不变。
方案2:编写自定义Page渲染器,单独处理ToolbarItem图标
如果不希望修改全局主题,仅调整ToolbarItem的图标显示效果,可在Android项目中添加自定义渲染器,在菜单加载完成后移除所有菜单项的图标色调配置:
- 在Android项目中新建渲染器类,示例代码如下:
using Android.Content; using Android.OS; using Android.Views; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; // 替换为自身项目的Android命名空间 using YourAppName.Droid; [assembly: ExportRenderer(typeof(ContentPage), typeof(NoTintToolbarRenderer))] namespace YourAppName.Droid { public class NoTintToolbarRenderer : PageRenderer { public NoTintToolbarRenderer(Context context) : base(context) { } public override bool OnCreateOptionsMenu(IMenu menu) { base.OnCreateOptionsMenu(menu); // 遍历所有Toolbar菜单项,移除图标tint for (int i = 0; i < menu.Size(); i++) { var menuItem = menu.GetItem(i); if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop && menuItem.Icon != null) { menuItem.Icon.SetTintList(null); } } return true; } } }
该方案仅影响页面Toolbar的菜单项图标,不会改动其他控件的默认主题表现。
iOS平台适配提示
后续做iOS适配时如果遇到同类图标变色问题,原因是iOS端UIToolbar默认会给图标应用全局tintColor,只需在iOS端自定义渲染逻辑时,将图标渲染模式设置为UIImageRenderingModeAlwaysOriginal即可保留原图标色彩。
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

