web-dev-qa-db-fra.com

Comment puis-je identifier que le dernier élément de RecyclerView est visible à l'écran?

J'ai un RecyclerView et j'ai ajouté une liste de données dans le RecyclerView. Je voulais ajouter plus de données dans la liste, lorsque le dernier RecyclerView élément est visible à l'écran. Après cela, je souhaite effectuer un appel de service Web et mettre à jour les données RecyclerView. Comment puis-je atteindre cet objectif?

Aucune suggestion?

17
Rajesh Koshti

Il existe plusieurs façons d'accomplir cela, mais une façon serait d'utiliser la méthode onBindViewHolder de votre adaptateur:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position == mData.length - 1) {
            // load more data here.
        }

        /// binding logic
    }

Lorsque la méthode de liaison est appelée avec la dernière position de votre source de données, c'est une bonne indication que la dernière cellule est sur le point d'être affichée et un bon moment pour déclencher un appel de rechargement. Vous devrez peut-être ajouter des protections supplémentaires à la condition pour vous assurer que vous ne chargez pas déjà plus de données, mais cela devrait vous aider à démarrer.

Une autre option consisterait à modifier votre LayoutManager. L'idée ici est de trouver la position du dernier élément visible. Si cette position est égale au dernier élément de votre jeu de données, vous devez déclencher un rechargement. Cet appel doit être effectué dans votre LayourManager'sonLayoutChildren & scrollVerticallyBy (en supposant que vous utilisez le défilement vertical):

    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {

        final int result = super.scrollVerticallyBy(dy, recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 

        return result;

    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);

        if (findLastVisibleItemPosition() == mData.length - 1) {
           loadMoreData();
        } 
    }

Comme précédemment, vous devrez vous assurer de ne pas déclencher un chargement de données plus d'une fois, car il est possible que cette condition se produise plus d'une fois.

J'espère que cela t'aides!

18
Gil Moshayof

Si quelqu'un tombe sur ce post c'est un tutoriel simple et rapide sur la façon de le faire:

Il vous suffit de:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        int visibleItemCount        = lm.getChildCount();
        int totalItemCount          = lm.getItemCount();
        int firstVisibleItemPosition= lm.findFirstVisibleItemPosition();

        // Load more if we have reach the end to the recyclerView
        if ( (visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
            loadMoreItems();
        }
    }
});

Ensuite, votre loadMoreItems () devrait ressembler à ceci:

private void loadMoreItems() {
    // init offset=0 the frist time and increase the offset + the PAGE_SIZE when loading more items
    queryOffset = queryOffset + PAGE_SIZE;
    // HERE YOU LOAD the next batch of items
    List<Items> newItems = loadItems(queryOffset, PAGE_SIZE);

    if (newItems.size() > 0) {
        items.addAll(newItems);
        adapter.notifyDataSetChanged();
    }
}
7
velval