Xamarin Forms TabBar自定义图标保色及类似Duolingo样式实现咨询
Xamarin Forms TabBar 保留图标原始色彩及实现彩色TabBar方案
一、保留TabBar图标原始色彩的解决方法
Xamarin Forms的TabBar默认会对图标进行灰度化处理,需要分iOS和Android平台单独配置取消着色:
iOS端实现
创建自定义TabbedPage渲染器,强制图标使用原始渲染模式:
using Xamarin.Forms.Platform.iOS; using Xamarin.Forms; using YourAppNamespace.iOS; [assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabBarRenderer))] namespace YourAppNamespace.iOS { public class CustomTabBarRenderer : TabbedRenderer { protected override void OnElementChanged(VisualElementChangedEventArgs e) { base.OnElementChanged(e); if (TabBar?.Items == null) return; foreach (var tabItem in TabBar.Items) { // 禁用系统自动着色,保留图标原始色彩 tabItem.Image = tabItem.Image?.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal); } } } }
Android端实现
有两种方式可以取消图标着色:
方式1:自定义渲染器
using Xamarin.Forms.Platform.Android; using Xamarin.Forms; using YourAppNamespace.Droid; using Android.Support.Design.Widget; [assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabBarRenderer))] namespace YourAppNamespace.Droid { public class CustomTabBarRenderer : TabbedPageRenderer { protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e) { base.OnElementChanged(e); if (ViewGroup != null && ViewGroup.GetChildAt(0) is TabLayout tabLayout) { for (int i = 0; i < tabLayout.TabCount; i++) { var tab = tabLayout.GetTabAt(i); if (tab?.Icon != null) { tab.Icon = Android.Support.V4.Graphics.Drawable.DrawableCompat.Wrap(tab.Icon); // 清除着色规则,保留原始色彩 Android.Support.V4.Graphics.Drawable.DrawableCompat.SetTintList(tab.Icon, null); } } } } } }
方式2:修改样式文件
在Android项目的Resources/values/styles.xml中添加自定义TabBar样式:
<style name="CustomTabStyle" parent="Widget.Design.TabLayout"> <item name="tabIconTint">@null</item> </style>
然后在MainActivity.cs中指定TabLayout使用该样式,或者在渲染器中动态设置。
二、实现类似Duolingo的彩色TabBar难度分析
Duolingo的TabBar核心特点是选中/未选中状态都保留彩色(未选中为低饱和度版本),部分图标带切换动画,实现难度中等,属于常规自定义TabBar需求,核心步骤如下:
1. 准备图标资源
为每个Tab准备两套图标:
- 选中状态:高饱和度的彩色图标
- 未选中状态:低饱和度/浅色调的彩色图标
2. Forms层切换逻辑
自定义TabbedPage,通过CurrentPageChanged事件动态切换图标:
public class CustomColoredTabbedPage : TabbedPage { public CustomColoredTabbedPage() { CurrentPageChanged += OnTabSwitched; } private void OnTabSwitched(object sender, EventArgs e) { foreach (var page in Children) { page.IconImageSource = page == CurrentPage ? GetSelectedIcon(page) : GetUnselectedIcon(page); } } // 自定义附加属性存储选中/未选中图标 public static readonly BindableProperty SelectedIconProperty = BindableProperty.CreateAttached("SelectedIcon", typeof(ImageSource), typeof(CustomColoredTabbedPage), null); public static readonly BindableProperty UnselectedIconProperty = BindableProperty.CreateAttached("UnselectedIcon", typeof(ImageSource), typeof(CustomColoredTabbedPage), null); public static ImageSource GetSelectedIcon(BindableObject obj) => (ImageSource)obj.GetValue(SelectedIconProperty); public static void SetSelectedIcon(BindableObject obj, ImageSource value) => obj.SetValue(SelectedIconProperty, value); public static ImageSource GetUnselectedIcon(BindableObject obj) => (ImageSource)obj.GetValue(UnselectedIconProperty); public static void SetUnselectedIcon(BindableObject obj, ImageSource value) => obj.SetValue(UnselectedIconProperty, value); }
在XAML中使用:
<local:CustomColoredTabbedPage> <ContentPage Title="首页" local:CustomColoredTabbedPage.SelectedIcon="home_selected.png" local:CustomColoredTabbedPage.UnselectedIcon="home_unselected.png"/> <ContentPage Title="学习" local:CustomColoredTabbedPage.SelectedIcon="study_selected.png" local:CustomColoredTabbedPage.UnselectedIcon="study_unselected.png"/> </local:CustomColoredTabbedPage>
3. 可选:添加切换动画
如果需要类似Duolingo的图标动效,可在平台渲染器中添加Native动画:
- iOS:监听Tab切换事件,给
TabBarItem的Image添加缩放动画 - Android:给Tab图标添加属性动画(如缩放、透明度变化)
整体来说,只要做好图标资源准备和状态切换逻辑,就能快速实现类似效果,没有技术壁垒。
内容的提问来源于stack exchange,提问作者IceKing
相关产品推荐
相关产品推荐

