2

I have a .Net MAUI app that uses Shell TabBar:

<TabBar>
    <Tab Title="Home" Icon="{StaticResource IconHome}">
        <ShellContent ContentTemplate="{DataTemplate local:MainPage}" />
    </Tab>
    <Tab Title="Coverage&#10;Calculator" Icon="{StaticResource IconCalculator}" >
        <ShellContent ContentTemplate="{DataTemplate calculator:CoverageCalculatorPage}" />
    </Tab>
    <Tab Title="Distributor&#10;Locator" Icon="{StaticResource IconLocator}">
        <ShellContent ContentTemplate="{DataTemplate locator:DistributorsLocatorPage}" />
    </Tab>
    <Tab Title="Scan&#10;QR Code" Icon="{StaticResource IconQrScanner}">
        <ShellContent ContentTemplate="{DataTemplate qrScanner:QrScannerPage}" />
    </Tab>        
    <Tab Title="More" Icon="{StaticResource IconMore}">
        <ShellContent ContentTemplate="{DataTemplate more:MoreFeaturesPage}" />
    </Tab>
</TabBar>

The icon color is set in Styles.xaml like this:

        <Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource LaticreteColor}, Dark={StaticResource LaticreteColor}}" />

Here is how the TabBar looks:

enter image description here

As my tabs needed more than one line of text, I applied a custom renderer for Android:

internal class LaticreteShellRenderer : ShellRenderer
{
    public LaticreteShellRenderer(Context context) : base(context) { }
    protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
    {
        return new LaticreteTabLayout();
    }
    public class LaticreteTabLayout : Java.Lang.Object, IShellBottomNavViewAppearanceTracker
    {
        public void ResetAppearance(BottomNavigationView bottomView)
        {
            throw new NotImplementedException();
        }

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

            var bottomNavView = bottomView.GetChildAt(0) as BottomNavigationMenuView;

            for (int i = 0; i < bottomNavView.ChildCount; i++)
            {
                var item = bottomNavView.GetChildAt(i) as BottomNavigationItemView;
                var itemTitle = item.GetChildAt(1);
                TextView smallTextView = (TextView)((BaselineLayout)itemTitle).GetChildAt(0);
                TextView largeTextView = (TextView)((BaselineLayout)itemTitle).GetChildAt(1);
                smallTextView.SetLines(2);
                largeTextView.SetLines(2);
            }
        }

This resets the tab's color:

enter image description here

I found that I can change the text color in the custom renderer like this:

                    smallTextView.SetTextColor(global::Android.Graphics.Color.Brown);
                largeTextView.SetTextColor(global::Android.Graphics.Color.Brown);

But I still don't know how to set the icon color, and how I can refer to my custom color set in App.xaml or Colors.xaml.

Why is TabBarUnselectedColor reset, and how can this be fixed?

Cfun
  • 8,442
  • 4
  • 30
  • 62
David Shochet
  • 5,035
  • 11
  • 57
  • 105

1 Answers1

1

The attached property TabBarUnselectedColor that you set is not applied because you have overrode the method responsible on doing so SetAppearance().

This can be fixed by simply calling that method from the base class at the begining like below:

public void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
    base.SetAppearance(bottomView, appearance);
    bottomView.SetMinimumHeight(180);
    ...
 }

Edit (full code)

no suitable method found to override"

internal class LaticreteShellRenderer : ShellRenderer
{
    public LaticreteShellRenderer(Context context) : base(context) { }

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

    public class LaticreteTabLayout : ShellBottomNavViewAppearanceTracker
    {

    public LaticreteTabLayout (IShellContext shellContext, ShellItem shellItem) : base(shellContext, shellItem)
    {
    }
        public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
        {
            base.SetAppearance(bottomView, appearance);

            bottomView.SetMinimumHeight(180);

            var bottomNavView = bottomView.GetChildAt(0) as BottomNavigationMenuView;

            for (int i = 0; i < bottomNavView.ChildCount; i++)
            {
                var item = bottomNavView.GetChildAt(i) as BottomNavigationItemView;
                var itemTitle = item.GetChildAt(1);
                TextView smallTextView = (TextView)((BaselineLayout)itemTitle).GetChildAt(0);
                TextView largeTextView = (TextView)((BaselineLayout)itemTitle).GetChildAt(1);
                smallTextView.SetLines(2);
                largeTextView.SetLines(2);
            }
        }
    }
Cfun
  • 8,442
  • 4
  • 30
  • 62
  • Thank you for your answer! But this line gives an error: 'Object' does not contain a definition for 'SetAppearance' – David Shochet Aug 29 '22 at 18:25
  • my bad i forgot the keyword `override` in the method signature, it might be the reason, strange that you don't have it in the code you posted – Cfun Aug 29 '22 at 18:39
  • no, it is my bad. I did not provide the full code. I added it to my question. Currently, I get "'LaticreteShellRenderer.LaticreteTabLayout.SetAppearance(BottomNavigationView, IShellAppearanceElement)': no suitable method found to override" – David Shochet Aug 29 '22 at 18:53
  • please check my edit – Cfun Aug 29 '22 at 19:06