Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement TabLayout.IOnTabSelectedListener.OnTabUnselected with TabbedPage.ToolbarPlacement="Bottom" - Xamarin Forms?

I just recently used android:TabbedPage.ToolbarPlacement="Bottom". I used to have the following code:

void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
{
   var playPage = Element.CurrentPage as NavigationPage;
   if (!(playPage.RootPage is PhrasesFrame))
      return;

   var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
   var playTab = tabLayout.GetTabAt(4);
   tab.SetText("Play");
   tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
   App.pauseCard = true;
}

Anyone knows how can I implement this with ToolbarPlacement="Bottom" ? I have implemented both BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener but can't find any reference for UnselectedTab if there is any.

Edit:

Previous custom renderer using the default tab position and implementing TabLayout:

namespace Japanese.Droid
{
    public class MyTabbedPageRenderer: TabbedPageRenderer, TabLayout.IOnTabSelectedListener
    {
        ViewPager viewPager;
        TabLayout tabLayout;
        bool setup;

        public MyTabbedPageRenderer(Context context): base(context){ }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // More codes here
        }

        void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
        {
            UpdateTab(tab);
        }

        void TabLayout.IOnTabSelectedListener.OnTabSelected(TabLayout.Tab tab)
        {
            UpdateTab(tab);
        }

        void TabLayout.IOnTabSelectedListener.OnTabUnselected(TabLayout.Tab tab)
        {
            var playPage = Element.CurrentPage as NavigationPage;
            if (!(playPage.RootPage is PhrasesFrame))
                return;

            var tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
            var playTab = tabLayout.GetTabAt(4);
            tab.SetText("Play");
            tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
            App.pauseCard = true;
        }

        void UpdateTab(TabLayout.Tab tab) 
        {
            // To have the logic only on he tab on position 1
            if (tab == null || tab.Position != 4)
            {
                return;
            }

            if (tab.Text == "Play")
            {
                tab.SetText("Pause");
                tab.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
                App.pauseCard = false;
            }
            else
            {
                tab.SetText("Play");
                tab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
                App.pauseCard = true;
            }
        }
    }
}

Current custom renderer using the ToolbarPlacement="Bottom":

namespace Japanese.Droid
{
    public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
    {
        public BottomTabPageRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
        {
            base.OnElementChanged(e);

            // More codes here
        }

        bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
        {
            base.OnNavigationItemSelected(item);

            UpdateTab(item)
        }

        void BottomNavigationView.IOnNavigationItemReselectedListener.OnNavigationItemReselected(IMenuItem item)
        {
            UpdateTab(item);
        }

        void UpdateTab(IMenuItem item)
        {
            var playTabId = 4;

            var title = item.TitleFormatted.ToString();
            if (item == null || item.ItemId != playTabId)
            {
                return;
            }

            if (item.ItemId == playTabId)
            {
                if (title == "Play")
                {
                    item.SetTitle("Pause");
                    item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
                    App.pauseCard = false;
                }
                else
                {
                    item.SetTitle("Play");
                    item.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
                    App.pauseCard = true;
                }
            }

        }

    }
}

So now my problem is I don't have any idea how will I implement the TabLayout.IOnTabSelectedListener.OnTabUnselected in the new custom renderer.

like image 752
Samantha J T Star Avatar asked Sep 20 '18 12:09

Samantha J T Star


2 Answers

There is no official stuff for OnTabReselected event for TabbedPage's bottom navigation or BottomNavigationView because It doesn't use TabLayout.Tab for a start. Many overridden methods of TabbedPageRenderer not being called like SetTabIcon. If you are using IOnTabSelectedListener interface(As your first part of code) you have three methods to use.

void OnTabReselected(Tab tab);
void OnTabSelected(Tab tab);          
void OnTabUnselected(Tab tab);

But when it comes to BottomNavigationView interface you have only two methods

void OnNavigationItemReselected
bool OnNavigationItemSelected

So we don't have built in OnTabUnselected method. Here you need to write custom code to make unseleted event.

I have tried this code without using custom renderer using 4 tabs pages & the xaml of tabbed written in MailPage.xaml file. First declare List<string> in App.xaml.cs file to store Title of all tabs

public static List<string> Titles {get;set;}

Add tabs pages title in above list from MainPage.xaml.cs file's OnAppearing method

protected override void OnAppearing()
{
    for (int i = 0; i < this.Children.Count; i++)
    {
        App.Titles.Add(this.Children[i].Title);
    }
}

Now go to your MyTabbedPage class in which is available in shared project.

public class MyTabbedPage : Xamarin.Forms.TabbedPage
{
    string selectedTab = string.Empty;
    string unSelectedTab = string.Empty;
    bool isValid;

    public MyTabbedPage()
    {
        On<Xamarin.Forms.PlatformConfiguration.Android>().SetToolbarPlacement(ToolbarPlacement.Bottom);

        this.CurrentPageChanged += delegate
        {
            unSelectedTab = selectedTab;
            selectedTab = CurrentPage.Title;
            if (App.Titles != null)
                isValid = true;
            else
                App.Titles = new List<string>();
            if (isValid)
            {
                MoveTitles(selectedTab);
               //Pass 0 index for tab selected & 1 for tab unselected
                var unSelecteTabTitle = App.Titles[1];
               //TabEvents(1); here you know which tab unseleted call any method
            }
        };
    }

    //This method is for to moving selected title on top of App.Titles list & unseleted tab title automatic shifts at index 1
    void MoveTitles(string selected)
    {
        var holdTitles = App.Titles;
        if (holdTitles.Count > 0)
        {
            int indexSel = holdTitles.FindIndex(x => x.StartsWith(selected));
            holdTitles.RemoveAt(indexSel);
            holdTitles.Insert(0, selected);
        }
        App.Titles = holdTitles;
    }    

}

Or you can make swith case like this

void TabEvents(int index)
{
  switch (index)
  {
    case 0:
        //Tab selected
        break;
    case 1:
         //Tab unselected
        break;
  }
}

Few things I should mention that MainPage.xaml.cs file inheriting MyTabbedPage

public partial class MainPage : MyTabbedPage

Structure of MainPage.xaml file

<?xml version="1.0" encoding="utf-8" ?>
<local:MyTabbedPage   

    <TabbedPage.Children>

        <NavigationPage Title="Browse">     
        </NavigationPage>   

    </TabbedPage.Children>
</local:MyTabbedPage>

Answer seems long but hope it help you.

like image 112
R15 Avatar answered Oct 01 '22 01:10

R15


As per G.Hakim's suggestion, I was able to do what I wanted to do by capturing the tab item I wanted to work on and do the necessary actions in BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected.

namespace Japanese.Droid
{
    public class BottomTabPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemSelectedListener, BottomNavigationView.IOnNavigationItemReselectedListener
    {
        // same as above

        bool BottomNavigationView.IOnNavigationItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
        {
            base.OnNavigationItemSelected(item);

            if(item.ItemId == 4 && item.TitleFormatted.ToString() == "Play") 
            {
                item.SetTitle("Pause");
                item.SetIcon(Resource.Drawable.ionicons_2_0_1_pause_outline_22);
                App.pauseCard = false;
                playTab = item;
            } 

            if(item.ItemId !=4 && playTab.TitleFormatted.ToString() == "Pause") 
            {
                playTab.SetTitle("Play");
                playTab.SetIcon(Resource.Drawable.ionicons_2_0_1_play_outline_25);
                App.pauseCard = true;
            }
            return true;
        }

        // same as above

    }
}
like image 37
Samantha J T Star Avatar answered Oct 01 '22 00:10

Samantha J T Star