Loupe

Android : scroller via du code dans un RecyclerView vertical

Il est parfois nécessaire d'amener votre utilisateur à un endroit précis d'une liste affichée via un RecyclerView. Dans cet article nous verrons comment scroller à une position précise mais aussi comment détecter la position à laquelle se trouve l'utilisateur. Cela permet par exemple d'afficher/masquer un FloatingActionButton.

Pour rappel, cet article fait partie d'une série sur le composant RecyclerView d'Android :

  1. Optimiser l'affichage de vos listes en utilisant un RecyclerView
  2. Ajouter des sticky headers sur vos RecyclerView
  3. Ajouter des en-têtes repliables (collapsible headers) sur vos RecyclerView
  4. Créer des RecyclerView horizontaux, les fameux "horizontal RecyclerView"
  5. Comment créer un RecyclerView infini / endless ?
  6. Afficher une liste d'éléments en mode grille avec un RecyclerView
  7. Ajouter des swipes actions sur un RecyclerView vertical.
  8. Cet article.
  9. Suspens.

Scroll à une position précise

La méthode la plus simple consiste à le demander directement au RecyclerView via sa méthode SmoothScrollToPosition :

_recyclerView.SmoothScrollToPosition(todayIndex);

Tout un article de blog pour ça... un peu léger non ? Ce n'est bien sûr pas aussi simple car cette méthode a le défaut de marcher de manière assez aléatoire. C'est un peu dommage lorsque vous voulez quelque chose qui fonctionne tout le temps :) L'astuce consiste à utiliser la méthode ScrollToPositionWithOffset du LinearLayoutManager. Cette dernière prend en paramètre un offset pour que l'élément que vous souhaitez afficher ne soit pas au bord de l'écran mais un peu plus centré. Dans cet exemple il est renseigné à 200 pixels :

var linearLayoutManager = 
   _recyclerView.GetLayoutManager() as LinearLayoutManager;
linearLayoutManager?.ScrollToPositionWithOffset(todayIndex, 200);

Détection de la position de l'utilisateur

La détection du Scroll est faite au moyen d'une classe dérivant de BaseScrollListener du SDK Android. Cette dernière peut être ajoutée sur un RecylerView et sa méthode OnScrolled est appelée à chaque événement de Scroll. Nous l'avions déjà utilisée dans l'article initial sur le RecyclerView.

Dans cette méthode, nous allons regarder si l'index ciblé est visible et, en fonction de cela, afficher ou masquer le bouton permettant à l'utilisateur de scroller vers celui-ci. Les informations nécessaires nous sont données par le LinearLayoutManager. Le code est encore une fois très simple :

internal class MonScrollListener : BaseScrollListener
{
    public int PositionOfNextToSeeItem { get; internal set; }
    private readonly LinearLayoutManager _layoutManager;
    private readonly View _scrollToNetxView;

    public MonScrollListener(
    RecyclerView recyclerView,
         View scrollToNetxView)
        : base("identifiant")
    {
        _layoutManager = recyclerView.GetLayoutManager() 
                as LinearLayoutManager;
        _scrollToNetxView = scrollToNetxView;
    }

    public override void OnScrolled(RecyclerView recyclerView, int dx, int dy)
    {
        base.OnScrolled(recyclerView, dx, dy);


        if (_layoutManager == null || PositionOfNextToSeeItem <= 0)
        {
            _scrollToNetxView.Visibility = ViewStates.Gone;
            return;
        }

        var firstVisible = _layoutManager.FindFirstVisibleItemPosition();
        var lastVisible = _layoutManager.FindLastVisibleItemPosition();
        if (PositionOfNextToSeeItem > lastVisible || PositionOfNextToSeeItem < firstVisible)
        {
            _scrollToNetxView.Visibility = ViewStates.Visible;
        }
        else
        {
            _scrollToNetxView.Visibility = ViewStates.Gone;
        }
    }
}

Et pour l'attacher au RecyclerView on utilise ce code :

_scrollListener = new MonScrollListener(_recyclerView, floatingActionButton);
_recyclerView.AddOnScrollListener(_scrollListener);

Cela permet par exemple en vidéo, l'affichage/masquage d'un bouton permettant d'accéder au jour actuel dans une application de gestion de séries :

 

Happy coding !

 

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus