Dynamically changing the selected tab tint color in Xamarin.Forms

Evgeny Zborovsky · January 2, 2019

Android

droid

Since Xamarin.Forms 3.1 a TabbedPage.BarSelectedItemColor property has been introduced and we can simply use it to achieve our goal.

XAML:

<TabbedPage
    xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
    android:TabbedPage.BarSelectedItemColor="Red">
</TabbedPage>

C#:

Xamarin.Forms.PlatformConfiguration.AndroidSpecific.TabbedPage.SetBarSelectedItemColor(%tabbedPage%, %color%);

iOS

ios

Unfortunately on iOS we have to implement the solution ourselves. Luckily there is a TintColor property on a UITabBar that we can use.

The solution

We will create an Effect using the knowledge listed above. The effect will have a single AttachedProperty which will represent the selected tab tint color:

public static class SelectedTabItemDynamicTintColorEffect
{
    public static readonly BindableProperty SelectedTabTintColorProperty =
        BindableProperty.CreateAttached("SelectedTabTintColor", typeof(Color), typeof(SelectedTabItemDynamicTintColorEffect), Color.Default);

    public static Color GetSelectedTabTintColor(BindableObject view) => (Color)view.GetValue(SelectedTabTintColorProperty);
    public static void SetSelectedTabTintColor(BindableObject view, Color value) => view.SetValue(SelectedTabTintColorProperty, value);
}

Next we will create the RoutingEffect:

public class TabbedPageSelectedTabItemDynamicTintColorEffect : RoutingEffect
{
    public TabbedPageSelectedTabItemDynamicTintColorEffect() : base($"XFDynamicSelectedTabTintColor.Effects.{nameof(TabbedPageSelectedTabItemDynamicTintColorEffect)}") { }
}

Here is the Android implementation:

public class TabbedPageSelectedTabItemDynamicTintColorEffect : PlatformEffect
{
    protected override void OnAttached() { }
    protected override void OnDetached() { }

    protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
    {
        base.OnElementPropertyChanged(args);

        if (args.PropertyName == SelectedTabItemDynamicTintColorEffect.SelectedTabTintColorProperty.PropertyName)
            SetTintColor();
    }

    void SetTintColor() =>
        Xamarin.Forms.PlatformConfiguration.AndroidSpecific.TabbedPage.SetBarSelectedItemColor(Element, SelectedTabItemDynamicTintColorEffect.GetSelectedTabTintColor(Element));
}

Here is the iOS implementation:

public class TabbedPageSelectedTabItemDynamicTintColorEffect : PlatformEffect
{
    protected override void OnAttached() { }
    protected override void OnDetached() { }

    protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
    {
        base.OnElementPropertyChanged(args);

        if (args.PropertyName == SelectedTabItemDynamicTintColorEffect.SelectedTabTintColorProperty.PropertyName)
            SetTintColor();
    }

    void SetTintColor()
    {
        var tabBar = Container.Subviews.First(v => v is UIKit.UITabBar);
        tabBar.TintColor = SelectedTabItemDynamicTintColorEffect.GetSelectedTabTintColor(Element).ToUIColor();
    }
}

In both cases we are monitoring SelectedTabTintColorProperty for changes and once changed simply applying a new TintColor.

Now we can just add the effect to our TabbedPage and change the tint color for example OnCurrentPageChanged so each tab will have its own tint color.

Full example can be found on github.

Twitter, Facebook