Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I change the background color of the Android tab with a renderer, while using a custom renderer to add some padding

In my application I set the bottom tab bar background color like this:

<Shell xmlns="http://xamarin.com/schemas/2014/forms" 
       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
       x:Class="M.Views.AppShell"
       NavBarIsVisible="True"
       xmlns:local="clr-namespace:Memorise"
       BackgroundColor="{DynamicResource ShellBackgroundColor}"
       TabBarBackgroundColor="{DynamicResource TabBarBackgroundColor}" 
       TabBarDisabledColor="{DynamicResource TabBarDisabledColor}" 
       TabBarForegroundColor="{DynamicResource TabBarForegroundColor}" 
       TabBarTitleColor="{DynamicResource TabBarTitleColor}" 
       TabBarUnselectedColor="{DynamicResource TabBarUnselectedColor}"

I create a custom renderer to add some side padding to the tabs on Android:

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new MarginedTabBarAppearance();
    }
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        if (App.devWidth == SIZE.L)
            bottomView.SetPadding(400, 0, 400, 0);
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}

Unfortunately this also has a side effect in that it sets the background color of the tab to white.

Does anyone have any knowledge of how I use this renderer and also change the background color to be the same as the DynamicResource ShellBackgroundColor?

Code with renderers commented out:

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    //protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    //{
    //    return new MarginedTabBarAppearance();
    //}
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        //if (App.devWidth == SIZE.L)
        //    bottomView.SetPadding(400, 0, 400, 0);
        //if (Application.Current.Resources["TabBarBackgroundColor"] is Xamarin.Forms.Color color1)
        //{
        //    bottomView.SetBackgroundColor(color1.ToAndroid());
        //}
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}

Tab bars with renderers commented out:

enter image description here

** Code with renderers not commented out:**

public class CustomShellRenderer : ShellRenderer
{
    public CustomShellRenderer(Context context)
        : base(context)
    {
    }

    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new MarginedTabBarAppearance();
    }
}

public class MarginedTabBarAppearance : IShellBottomNavViewAppearanceTracker
{
    public void Dispose()
    {
    }

    public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        if (App.devWidth == SIZE.L)
            bottomView.SetPadding(400, 0, 400, 0);
        if (Application.Current.Resources["TabBarBackgroundColor"] is Xamarin.Forms.Color color1)
        {
            bottomView.SetBackgroundColor(color1.ToAndroid());
        }
    }

    public void ResetAppearance(BottomNavigationView bottomView)
    {
    }
}

Tab bars with renderers not commented out:

enter image description here

Updated code suggested by Mihail:

public class MarginedTabBarAppearance :    ShellBottomNavViewAppearanceTracker
{

public MarginedTabBarAppearance(IShellContext shellContext, ShellItem shellItem)
    : base(shellContext, shellItem)
{
}

public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
    base.SetAppearance(bottomView, appearance);

    bottomView.SetPadding(400, 0, 400, 0);

    if (Application.Current.Resources.ContainsKey("TabBarBackgroundColor") && 
        Application.Current.Resources["TabBarBackgroundColor"] is Color tabColor)
    {
        bottomView.SetBackgroundColor(tabColor.ToAndroid());
    }
}
}
like image 816
Alan2 Avatar asked Jul 03 '20 16:07

Alan2


2 Answers

In your SetAppearance method, you can set the background color like this:

bottomView.SetBackgroundColor(Android.Graphics.Color.Red);

However, the SetBackgroundColor requires a color of type Android.Graphics.Color and I see that you wish to take the color from a DynamicResource, which will return a Xamarin.Forms.Color. The good thing is that both color classes are easily convertable so we'll only need to take the current value of the DynamicResource:

if (Application.Current.Resources["CustomTabBackgroundColor"] is Xamarin.Forms.Color color)
{
    bottomView.SetBackgroundColor(color.ToAndroid());
}

Here, CustomTabBackgroundColor is the key for your color and color.ToAndroid() does the convertion between the 2 classes (from Xamarin's to Android's one).

UPDATE

Due to an update to the question, I'll add that the issue with the styles/colors resetting isn't in this case due to the backround change, but it's due to something else entirely. The way that a new view appearance is being set (return new MarginedTabBarAppearance();) resets all of the default styles. Since we are implementing everything from an interface and not deriving from the base class, we can't take anything from the already preset values. In order to fix that, we'll need to change the way the MarginedTabBarAppearance class is being implemented:

public class MarginedTabBarAppearance : ShellBottomNavViewAppearanceTracker
{
    public MarginedTabBarAppearance(IShellContext shellContext, ShellItem shellItem)
        : base(shellContext, shellItem)
    {
    }

    public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
    {
        base.SetAppearance(bottomView, appearance);

        bottomView.SetPadding(400, 0, 400, 0);

        if (Application.Current.Resources.ContainsKey("TabBarBackgroundColor") && 
            Application.Current.Resources["TabBarBackgroundColor"] is Color tabColor)
        {
            bottomView.SetBackgroundColor(tabColor.ToAndroid());
        }
    }
}

Also, you will have to change your CreateBottomNavViewAppearanceTracker method like this:

protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
    return new MarginedTabBarAppearance(this, shellItem);
}

This way we'll take everything that we have already styled and we'll simply change what we'll need.

like image 138
Mihail Duchev Avatar answered Nov 15 '22 11:11

Mihail Duchev


Change the background color of TabBar with SetBackgroundColor method in SetAppearance.

Original screenshot:

enter image description here

Add the code in SetAppearance method:

bottomView.SetBackgroundColor(Android.Graphics.Color.Green);

Screenshot:

enter image description here

like image 25
Wendy Zang - MSFT Avatar answered Nov 15 '22 10:11

Wendy Zang - MSFT