如何使用TabbedPage.ToolbarPlacement =“ Bottom”-Xamarin Forms实现TabLayout.IOnTabSelectedListener.OnTabUnselected?

时间:2018-09-20 12:00:36

标签: xamarin xamarin.forms xamarin.android

我最近使用过android:TabbedPage.ToolbarPlacement="Bottom"。我以前有以下代码:

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;
}

任何人都知道如何使用ToolbarPlacement="Bottom"来实现它?我已经实现了BottomNavigationView.IOnNavigationItemSelectedListenerBottomNavigationView.IOnNavigationItemReselectedListener,但是找不到UnselectedTab的任何引用。

编辑:

使用默认标签位置并实现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;
            }
        }
    }
}

使用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;
                }
            }

        }

    }
}

所以现在我的问题是我不知道如何在新的自定义渲染器中实现TabLayout.IOnTabSelectedListener.OnTabUnselected

2 个答案:

答案 0 :(得分:3)

{a: A} & {[n: string]: B}的底部导航或OnTabReselected事件没有官方资料, TabbedPage,因为它一开始并不使用BottomNavigationViewTabLayout.Tab的许多重写方法没有像TabbedPageRenderer那样被调用。如果您使用的是SetTabIcon界面(作为代码的第一部分),则可以使用三种方法。

IOnTabSelectedListener

但是当涉及void OnTabReselected(Tab tab); void OnTabSelected(Tab tab); void OnTabUnselected(Tab tab); 接口时,您只有两种方法

BottomNavigationView

因此我们没有内置void OnNavigationItemReselected bool OnNavigationItemSelected 方法。在这里,您需要编写自定义代码以进行不删除的事件。

我尝试过使用4个标签页和MailPage.xaml文件中编写的选项卡式xaml而不使用自定义渲染器的代码。首先在OnTabUnselected文件中声明List<string>,以存储所有标签的App.xaml.cs

Title

通过public static List<string> Titles {get;set;} 文件的MainPage.xaml.cs方法在以上列表中添加标签页标题

OnAppearing

现在转到您的protected override void OnAppearing() { for (int i = 0; i < this.Children.Count; i++) { App.Titles.Add(this.Children[i].Title); } } 类,该类在共享项目中可用。

MyTabbedPage

或者您也可以像这样

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;
    }    

}

我应该提到的几件事是void TabEvents(int index) { switch (index) { case 0: //Tab selected break; case 1: //Tab unselected break; } } 文件继承了MainPage.xaml.cs

MyTabbedPage

MainPage.xaml文件的结构

public partial class MainPage : MyTabbedPage

答案似乎很长,但希望能对您有所帮助。

答案 1 :(得分:2)

根据G.Hakim的建议,我可以通过捕获要处理的选项卡项并在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

    }
}