pocheshire / BottomNavigationBar

Bottom Navigation Bar for Xamarin
214 stars 70 forks source link

Icon doesn't get highlighted on Android when tab changes programmatically. #88

Open toyins46 opened 5 years ago

toyins46 commented 5 years ago

I’m using the BottomBarPage package. I’m changing the Tab on the fly programmatically, however the icon at the bottom doesn’t get highlighted for Android when there’s a tab change. It works well on iOS on the hand. I tried James Montemagno’s code, I couldn’t get it to work with BottomBarPage package. This is the link to his code

How do I get the Icon highlighted when there is a Tab Page happening programmatically for BottomBarPage?

Below is my code.

public AndroidMainPage(int indexPage)
        {
            InitializeComponent();
            NavigationPage.SetHasNavigationBar(this, false);
            CurrentPageChanged += MainPage_CurrentPageChanged;
            CurrentPage = Children[indexPage];
            CurrentPage.Appearing += (s, a) => Children[indexPage].Icon = new FileImageSource() { File = "quizzes_selected.png" };
            CurrentPage.Disappearing += (s, a) => Children[indexPage].Icon = new FileImageSource() { File = "quizzes.png" };
            _currentPage = CurrentPage;
        }

private void MainPage_CurrentPageChanged(object sender, EventArgs e)
        {
            IIconChange currentBinding;

            if (_currentPage != null)
            {
                currentBinding = ((NavigationPage)_currentPage).CurrentPage.BindingContext as IIconChange;
                if (currentBinding != null)
                    currentBinding.IsSelected = false;
            }

            _currentPage = CurrentPage;
            currentBinding = ((NavigationPage)_currentPage).CurrentPage.BindingContext as IIconChange;
            if (currentBinding != null)
                currentBinding.IsSelected = true;

            UpdateIcons?.Invoke(this, EventArgs.Empty);
        }

Android BottomBarPage Renderer

[assembly: ExportRenderer(typeof(AndroidMainPage), typeof(MyTabbedPageRenderer))]
namespace TabPageDemo.Android.Renderers
{
    public class MyTabbedPageRenderer : BottomBarPageRenderer 
    {
        bool setup;
        TabLayout layout;
        public MyTabbedPageRenderer()
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<BottomBarPage> e)
        {
            if (e != null) base.OnElementChanged(e);
            if (Element != null)
            {
                ((AndroidMainPage)Element).UpdateIcons += Handle_UpdateIcons;
            }
        }

        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (layout == null && e.PropertyName == "Renderer")
            {
                layout = (TabLayout)ViewGroup.GetChildAt(1);
                //ClaimAllView.View view = (ClaimAllView.View)GetChildAt(1);
            }
        }

        void Handle_UpdateIcons(object sender, EventArgs e)
        {
            TabLayout tabs = layout;

            if (tabs == null)
                return;

            for (var i = 0; i < Element.Children.Count; i++)
            {
                var child = Element.Children[i].BindingContext as IIconChange;
                if (child == null) continue;
                var icon = child.CurrentIcon;
                if (string.IsNullOrEmpty(icon))
                    continue;

                TabLayout.Tab tab = tabs.GetTabAt(i);
                SetCurrentTabIcon(tab, icon);
            }
        }

        void SetCurrentTabIcon(TabLayout.Tab tab, string icon)
        {
            tab.SetIcon(IdFromTitle(icon, ResourceManager.DrawableClass));
        }

        int IdFromTitle(string title, Type type)
        {
            string name = Path.GetFileNameWithoutExtension(title);
            int id = GetId(type, name);
            return id;
        }

        int GetId(Type type, string memberName)
        {
            object value = type.GetFields().FirstOrDefault(p => p.Name == memberName)?.GetValue(type)
                ?? type.GetProperties().FirstOrDefault(p => p.Name == memberName)?.GetValue(type);
            if (value is int)
                return (int)value;
            return 0;
        }
    }

}

Using the Renderer, the tab variable is always null from this

TabLayout.Tab tab = tabs.GetTabAt(i);

Any suggestion?