Loupe

Etendre les fonctionnalités d'un renderer Xamarin.Forms

Dans un précédent article, je vous ai montré comment implémenter une nouvelle fonctionnalité dans votre application Xamarin.Forms, via les renderers.

Mais cette technique ne me convenait pas car je suis passé par la méthode OnNavigationItemSelected et une comparaison de chaîne de caractères pour savoir si l'utilisateur avait cliqué sur le même onglet alors qu'Android propose la méthode OnNavigationItemReselected qui fait exactement ce que je voulais.

Qu'à cela ne tienne, nous allons donc utiliser cette méthode ! Seul problème, le TabbedPageRenderer de Xamarin.Forms n'implémente pas BottomNavigationView.IOnNavigationItemReselectedListener donc nous devons le faire par nous-même.

La technique est simple : nous allons crééer un Renderer custom qui implémente cette interface et qui va récupérer l'objet BottomNavigationView présent dans le Renderer de base pour lui rajouter cette fonctionnalité (via un appel à SetOnNavigationItemReselectedListener) :

public class CustomTabbedPageRenderer : TabbedPageRenderer, BottomNavigationView.IOnNavigationItemReselectedListener
{
    public CustomTabbedPageRenderer(Context context)
        : base(context)
    {
    }
        
    protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
    {
        base.OnElementChanged(e);

        if(e.OldElement == null && e.NewElement != null)
        {
            for (int i = 0; i <= this.ViewGroup.ChildCount - 1; i++)
            {
                var childView = this.ViewGroup.GetChildAt(i);
                if(childView is ViewGroup viewGroup)
                {
                    for (int j = 0; j <= viewGroup.ChildCount - 1; j++)
                    {
                        var childRelativeLayoutView = viewGroup.GetChildAt(j);
                        if(childRelativeLayoutView is BottomNavigationView bottomNavigationView)
                        {
                            bottomNavigationView.SetOnNavigationItemReselectedListener(this);
                        }
                    }
                }
            }
        }
    }

    void BottomNavigationView.IOnNavigationItemReselectedListener.OnNavigationItemReselected(IMenuItem item)
    {
        if (Element.CurrentPage is ContentPage contentPage)
        {
            if (contentPage.Content is Layout<Xamarin.Forms.View> layout)
            {
                var listView = layout.Children.OfType<Xamarin.Forms.ListView>().FirstOrDefault();
                if (listView != null)
                {
                    listView.ScrollTo((listView.ItemsSource as IEnumerable<object>).First(), ScrollToPosition.Start, true);
                }
            }
        }
    }
}

Le code de notre Renderer, à proprement parlé, devient donc beaucoup plus simple :

public class MainPageRenderer : CustomTabbedPageRenderer
{
    public MainPageRenderer(Context context) 
        : base(context)
    {
    }
}

Et le tour est joué ! 

 

Happy coding! :)

 

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus