Forum Xamarin Xamarin.Forms

Shell Bottom Tabs, how do I get full color icons?

BrienKingBrienKing USMember ✭✭

I'm not a fan of the monochrome icons, is there a way to get it to use the full color icons there?

Answers

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    In the android platform, Yes, you can achieve it. Here is running sreenshot.

    You should create a custom renderer for shell. Then override the CreateBottomNavViewAppearanceTracker method, achieve the MyShellBottomNavViewAppearanceTracker class

     [assembly: ExportRenderer(typeof(ShellActionBar.AppShell), typeof(MyShellRenderer))]
     namespace ShellActionBar
     {
       public class MyShellRenderer : ShellRenderer
     {
        public MyShellRenderer(Context context) : base(context)
        {
        }
    
      protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
        {
            return new MyShellBottomNavViewAppearanceTracker(this);
        }
       }
      }
    

    MyShellBottomNavViewAppearanceTracker class, set the bottomView.ItemIconTintList = null; to null

           internal class MyShellBottomNavViewAppearanceTracker : IShellBottomNavViewAppearanceTracker
    {
        private MyShellRenderer myShellRenderer;
    
        public MyShellBottomNavViewAppearanceTracker(MyShellRenderer myShellRenderer)
        {
            this.myShellRenderer = myShellRenderer;
        }
    
        public void Dispose()
        {
            //throw new System.NotImplementedException();
        }
    
        public void ResetAppearance(BottomNavigationView bottomView)
        {
            //throw new System.NotImplementedException();
        }
    
        public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
        {
            bottomView.ItemIconTintList = null;
        }
    }
    
  • BrienKingBrienKing USMember ✭✭

    Thank you for the quick response, I'll give that a shot!

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    Ok, waitting for your update.

  • BrienKingBrienKing USMember ✭✭

    @LeonLu said:
    Ok, waitting for your update.

    Well your solution got me where I wanted to be, so thank you for that!

    For others reading this and looking for the same answer I'll fill in a few of the gaps that I had to figure out in the hopes that it helps you.

    First, these classes need to be in the Platform Specific project. In this case I put it in my Android project. If you're doing iOS then you would create these classes in your iOS project but you'll have different using statements at the top. If you are doing both platforms then these classes need to be in both projects.

    I put both classes in the same class file CustomShellRenderer (I renamed it from MyShellRenderer). You could put them in separate files, but there is so little code, there really isn't a reason to.

    You will need the following using statements at the top of your class file.

    using Android.Content;
    using Android.Support.Design.Widget;
    using System;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    

    For the assembly ExportRender, the first parameter is the type of the page that has the Shell control on it in your Xamarin Forms project.

    In the code above the line

            bottomView.ItemIconTintList = null;
    

    is in the Method

            public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
    

    However, for me, it needed to be in this method

            public void ResetAppearance(BottomNavigationView bottomView)
    

    So here is the full code that works for me:

    using Android.Content;
    using Android.Support.Design.Widget;
    using System;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.Android;
    
    [assembly: ExportRenderer(typeof(CaseCmdrPro.DcwDashboard), typeof(CaseCmdrPro.CustomShellRenderer))]
    namespace CaseCmdrPro
    {
    
        public class CustomShellRenderer: ShellRenderer
        {
            public CustomShellRenderer(Context context) : base(context)
            {
            }
    
            protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
            {
                return new CustomShellBottomNavViewAppearanceTracker(this);
            }
        }
    
        internal class CustomShellBottomNavViewAppearanceTracker : IShellBottomNavViewAppearanceTracker
        {
            private CustomShellRenderer m_shellRenderer = null;
    
            public CustomShellBottomNavViewAppearanceTracker(CustomShellRenderer p_shellRenderer)
            {
                m_shellRenderer = p_shellRenderer;
            }
    
            public void Dispose()
            {
                //throw new System.NotImplementedException();
            }
    
            public void ResetAppearance(BottomNavigationView bottomView)
            {
                bottomView.ItemIconTintList = null;
            }
    
            public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
            {
                bottomView.ItemIconTintList = null;
            }
        }
    }
    
  • LeonLuLeonLu Member, Xamarin Team Xamurai

    Thanks for your sharing.

  • In the iOS platform, to get full color icons in Shell Bottom Tab

    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;

    [assembly: ExportRenderer(typeof(SaiShellApp.ShellApp), typeof(SaiShellApp.iOS.MyShellRenderer))]
    namespace SaiShellApp.iOS
    {
    public class MyShellRenderer : ShellRenderer
    {
    protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
    {
    var renderer = base.CreateShellSectionRenderer(shellSection);
    if (renderer != null)
    {
    }
    return renderer;
    }

        protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
        {
            return new TabbarIconsAppearance();
        }
    }
    public class TabbarIconsAppearance : IShellTabBarAppearanceTracker
    {  
        public void Dispose()
        {
        }
    
        public void ResetAppearance(UITabBarController controller)
        {          
            if (controller.TabBar.Items != null)
            {
                foreach (UITabBarItem tabbaritem in controller.TabBar.Items)
                {
                    tabbaritem.Image = tabbaritem.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                    tabbaritem.SelectedImage = tabbaritem.SelectedImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                }
            }
        }
    
        public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
        {
            if (controller.TabBar.Items != null)
            {
                foreach (UITabBarItem tabbaritem in controller.TabBar.Items)
                {
                    tabbaritem.Image = tabbaritem.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                    tabbaritem.SelectedImage = tabbaritem.SelectedImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                }
            }
        }
    
        public void UpdateLayout(UITabBarController controller)
        {
    
        }
    } }
    
  • ScottKuhlScottKuhl USMember

    @SaiKrishnaKSV There is a bug in your iOS implementation, the colors are not set on initial startup because controller.TabBar.Items is null. If you change to another tab, then the icons will change to color. Implementing the UpdateLayout method fixes it.

    Here is my complete code example for iOS.

    using System;
    using UIKit;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    
    [assembly: ExportRenderer(typeof(MyApp.AppShell), typeof(MyApp.iOS.Renderers.CustomShellRenderer))]
    
    namespace MyApp.iOS.Renderers
    {
        public class CustomShellRenderer : ShellRenderer
        {
            protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
            {
                var renderer = base.CreateShellSectionRenderer(shellSection);
                if (renderer != null)
                {
                }
                return renderer;
            }
    
            protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
            {
                return new TabbarIconsAppearance();
            }
        }
    
        public class TabbarIconsAppearance : IShellTabBarAppearanceTracker
        {
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            public void ResetAppearance(UITabBarController controller)
            {
                DisplayColorIcons(controller);
            }
    
            public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
            {
                DisplayColorIcons(controller);
            }
    
            public void UpdateLayout(UITabBarController controller)
            {
                DisplayColorIcons(controller);
            }
    
            protected virtual void Dispose(bool disposing)
            {
            }
    
            private void DisplayColorIcons(UITabBarController controller)
            {
                if (controller.TabBar.Items != null)
                {
                    foreach (UITabBarItem tabbaritem in controller.TabBar.Items)
                    {
                        tabbaritem.Image = tabbaritem.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                        tabbaritem.SelectedImage = tabbaritem.SelectedImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                    }
                }
            }
        }
    }
    
    
  • solarcloud7solarcloud7 USMember
    edited September 22

    @ScottKuhl and @SaiKrishnaKSV Thank you both for your contributions! They helped me so much!

    Scott is correct about SaiKrishnaKSV's submission not having the colors set on initial startup. The only thing I needed to tweak for Scott's answer to work for me was:
    if (tabbaritem.Image == null) continue;

    Here is the updated DisplayColorIcons() method of ScottKuhl's that i used.

    private void DisplayColorIcons(UITabBarController controller)
    {
        if (controller.TabBar.Items != null)
        {
            foreach (UITabBarItem tabbaritem in controller.TabBar.Items)
            {
                if (tabbaritem.Image == null) continue;
    
                tabbaritem.Image = tabbaritem.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
                tabbaritem.SelectedImage = tabbaritem.SelectedImage.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
            }
        }
    }
    
Sign In or Register to comment.