【问题标题】:How to implement TabLayout.IOnTabSelectedListener.OnTabUnselected with TabbedPage.ToolbarPlacement="Bottom" - Xamarin Forms?如何使用 TabbedPage.ToolbarPlacement="Bottom" - Xamarin Forms 实现 TabLayout.IOnTabSelectedListener.OnTabUnselected?
【发布时间】:2019-02-24 17:48:20
【问题描述】:

我最近才使用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

【问题讨论】:

  • 请详细说明一下。我不明白你的意思。
  • @YorkShen-MSFT 很抱歉造成混乱。我现在将 ToolbarPlacement="Bottom" 用于我的 Xamarin.Forms Android 应用程序。在 android 中使用默认的 tabbar 位置之前,我曾经扩展 TabLayout.IOnTabSelectedListener 来处理诸如 OnTabReselectedOnTabSelectedOnTabUnselected 之类的事件。现在我不知道如何使用 BottomNavigationView 处理 OnTabUnselected。这有意义吗?
  • @SamanthaJTStar - 你们有兴趣使用自定义渲染器吗?
  • @Arvindraja 我正在使用自定义渲染器。请参阅上面的修改
  • 那么您是在底部导航视图中寻找未选择的事件吗?

标签: xamarin xamarin.forms xamarin.android


【解决方案1】:

TabbedPage 的底部导航或OnTabReselected 事件没有官方的东西 BottomNavigationView 因为它不使用 TabLayout.Tab 作为开始。 TabbedPageRenderer 的许多重写方法不像 SetTabIcon 那样被调用。如果您使用IOnTabSelectedListener 接口(作为您的第一部分代码),您可以使用三种方法。

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

但是当涉及到BottomNavigationView 接口时,你只有两个方法

void OnNavigationItemReselected
bool OnNavigationItemSelected

所以我们没有内置OnTabUnselected 方法。在这里,您需要编写自定义代码来制作未选择的事件。

我在没有使用自定义渲染器的情况下尝试了这段代码,使用了 4 个标签页和在 MailPage.xaml 文件中编写的标签页 xaml。首先在App.xaml.cs文件中声明List&lt;string&gt;以存储所有标签的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

public partial class MainPage : MyTabbedPage

MainPage.xaml 文件结构

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

    <TabbedPage.Children>

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

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

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

【讨论】:

    【解决方案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
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多