Sunday, October 14, 2018

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

Leave a Comment

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.

2 Answers

Answers 1

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.

Answers 2

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      } } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment