c# - 在 Android 中重新选择选项卡时如何更改 TabbedPage 图标?

标签 c# xamarin xamarin.forms

我有一个使用 Xamarin Forms TabbedPage 的应用程序,它具有允许用户暂停和播放页面的功能。请看下面的代码。

共享代码

public partial class MainPage : TabbedPage
{
   public MainPage()
   {
      InitializeComponent();

      var homePage = new NavigationPage(new HomePage())
      { 
         Title = "Home",
         Icon = "ionicons_2_0_1_home_outline_25.png"
      };

      var phrasesPage = new NavigationPage(new PhrasesPage())
      {
         Title = "Play",
         Icon = "ionicons_2_0_1_play_outline_25.png"
       };

       Children.Add(homePage);
       Children.Add(phrasesPage);
   }
}

在 iOS 渲染器中:

public class TabbedPageRenderer : TabbedRenderer
{
   private MainPage _page;
   protected override void OnElementChanged(VisualElementChangedEventArgs e)
  {
      base.OnElementChanged(e);
      var tabbarController = (UITabBarController)this.ViewController;
      if (null != tabbarController)
      {
         tabbarController.ViewControllerSelected += OnTabBarReselected;
       }
   }

   void OnTabBarReselected(object sender, UITabBarSelectionEventArgs e)
   {
      var tabs = Element as TabbedPage;
      var playTab = tabs.Children[4];

      if (TabBar.SelectedItem.Title == "Play") {
         if (tabs != null)
         {
            playTab.Title = "Pause";
            playTab.Icon = "ionicons_2_0_1_pause_outline_22.png";
         }
         App.pauseCard = false;
       }
       else {
        if (tabs != null) {
           playTab.Title = "Play";
           playTab.Icon = "ionicons_2_0_1_play_outline_25.png";
       }
       App.pauseCard = true;
    }
}

安卓渲染器

public class MyTabbedPageRenderer: TabbedPageRenderer, TabLayout.IOnTabSelectedListener
{
    if (e.PropertyName == "Renderer")
    {
       viewPager = (ViewPager)ViewGroup.GetChildAt(0);
       tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
       setup = true;

       ColorStateList colors = null;
       if ((int)Build.VERSION.SdkInt >= 23)
       {
           colors = Resources.GetColorStateList(Resource.Color.icon_tab, Forms.Context.Theme);
       }
       else
       {
           colors = Resources.GetColorStateList(Resource.Color.icon_tab);
       }

       for (int i = 0; i < tabLayout.TabCount; i++)
       {
           var tab = tabLayout.GetTabAt(i);
           var icon = tab.Icon;
           if (icon != null)
           {
               icon = Android.Support.V4.Graphics.Drawable.DrawableCompat.Wrap(icon);
               Android.Support.V4.Graphics.Drawable.DrawableCompat.SetTintList(icon, colors);
           }
       }
   }

   void TabLayout.IOnTabSelectedListener.OnTabReselected(TabLayout.Tab tab)
   {
      var tabs = Element as TabbedPage;
      var playTab = tabs.Children[4];
      var selectedPosition = tab.Position;

      if(selectedPosition == 4) 
      {
         if (playTab.Title == "Play")
         {
            if (tabs != null)
            {
               playTab.Title = "Pause";
               playTab.Icon = "ionicons_2_0_1_pause_outline_22.png";
            }
            App.pauseCard = false;
          }
          else
          {
             if (tabs != null)
             {
                playTab.Title = "Play";
                playTab.Icon = "ionicons_2_0_1_play_outline_25.png";
             }
             App.pauseCard = true;
           }
         }
    }
}

这在 iOS 中完美运行。但不知何故,在 Android 中,只有 Title 会发生变化,而 Icon 不会。任何人都知道我缺少什么或应该怎么做?此外,这是否可以在共享代码中完成,而不是在每个平台的代码中重复几乎完全相同的行?

最佳答案

您可以通过使用在 TabRendererOnTabReselected 参数中传递给您的选项卡来完成此操作。

您可以使用此对象移动您的整个逻辑。

这是我的整个渲染器文件(Android):

[assembly: ExportRenderer(typeof(SWTabSelection.MainPage), typeof(SWTabSelection.Droid.MyTabbedPageRenderer))]
namespace SWTabSelection.Droid
{
    public class MyTabbedPageRenderer : TabbedPageRenderer, TabLayout.IOnTabSelectedListener
    {
        private ViewPager viewPager;
        private TabLayout tabLayout;
        private bool setup;

        public MyTabbedPageRenderer() { }

        public MyTabbedPageRenderer(Context context) : base(context)
        {
            //Use this constructor for newest versions of XF saving the context parameter 
            // in a field so it can be used later replacing the Xamarin.Forms.Forms.Context which is deprecated.
        }

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

            if (e.PropertyName == "Renderer")
            {
                viewPager = (ViewPager)ViewGroup.GetChildAt(0);
                tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
                setup = true;

                ColorStateList colors = GetTabColor();

                for (int i = 0; i < tabLayout.TabCount; i++)
                {
                    var tab = tabLayout.GetTabAt(i);

                    SetTintColor(tab, colors);
                }
            }
        }


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

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

        SetTintColor(tab, GetTabColor());

    }

        void SetTintColor(TabLayout.Tab tab, ColorStateList colors)
        {
            var icon = tab?.Icon;
            if(icon != null)
            {
                icon = Android.Support.V4.Graphics.Drawable.DrawableCompat.Wrap(icon);
                Android.Support.V4.Graphics.Drawable.DrawableCompat.SetTintList(icon, colors);            
            }
        }

        ColorStateList GetTabColor()
        {
            return ((int)Build.VERSION.SdkInt >= 23) 
                ? Resources.GetColorStateList(Resource.Color.icon_tab, Forms.Context.Theme)
                               : Resources.GetColorStateList(Resource.Color.icon_tab);
        }

    }
}

我在上面的代码中遇到的唯一问题是图标没有采用 Tint 颜色,因此创建了一个函数,其逻辑与设置 Tint 的逻辑相同,我在 Tab Reselection 上使用它。如果您的应用中只有一个选项卡,您可以在 Android 主题/样式 xml 中设置全局色调。

希望这对您有所帮助。

关于c# - 在 Android 中重新选择选项卡时如何更改 TabbedPage 图标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49585447/

相关文章:

c# - AppDomain,处理异常

c# - 如何检查字符是否为整数

c# - 使用 shell 时如何更改 iOS 中状态栏的颜色

c# - 如何清除所选项目 Xamarin 列表

c# - 为什么在 Unity 5 中,我的 2D 触发器对撞机只感知与某些对象的碰撞而不感知其他对象的碰撞?

c# - SEC7123 : Request header Key was not present in the Access-Control-Allow-Headers list

c# - DataTemplateSelector CreateContent 抛出 InvalidOperationException

c# - 在 C# 中的 Android Activity 之间传递自定义对象

android - Xamarin Forms - 如何检查 Android 上 RequestIgnoreBatteryOptimizations 权限的设置

xamarin.forms - Xamarin 表格 : Increase the editor height based on the character count