Comment faire défiler vers le bas D'un RecyclerView? scrollToPosition ne fonctionne pas

Je voudrais faire défiler vers le bas de la liste RecyclerView après le chargement de l'activité.

GENERIC_MESSAGE_LIST = (ArrayList) intent.getExtras().getParcelableArrayList(ConversationsAdapter.EXTRA_MESSAGE);
conversationView = (RecyclerView) findViewById(R.id.list_messages);
conversationView.setHasFixedSize(true);
conversationViewLayoutManager = new LinearLayoutManager(this);
conversationView.setLayoutManager(conversationViewLayoutManager);
conversationViewAdapter = new ConversationAdapter(GENERIC_MESSAGE_LIST, this);
conversationView.setAdapter(conversationViewAdapter);

conversationView.scrollTo(...) lève une exception pour ne pas être pris en charge dans RecyclerView, et conversationView.scrollToPosition(...) ne semble rien faire.

Après le bloc de code ci-dessus, j'ai ajouté

conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size() + 1)

Qui ne fonctionne pas. Il y a 30 éléments dans GENERIC_MESSAGE_LIST.

104
demandé sur waylaidwanderer 2014-10-27 06:17:09

15 réponses

Juste ensemble setStackFromEnd=true ou setReverseLayout=true de sorte que LLM mettra en page les éléments de fin.

La différence entre ces deux est que setStackFromEnd définira la vue pour afficher le dernier élément, la direction de mise en page restera la même. (Ainsi, dans une vue de recycleur horizontal de gauche à droite, le dernier élément sera affiché et le défilement vers la gauche affichera les éléments précédents)

Alors que {[4] } modifiera l'ordre des éléments ajoutés par L'Adaptateur. La mise en page commencera à partir de la dernière élément, qui sera le plus à gauche dans une vue LTR Recycler, puis, le défilement vers la droite montrera les éléments précédents.

Échantillon:

final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setReverseLayout(true);
_listView.setLayoutManager(linearLayoutManager);

Voir documentation pour plus de détails.

158
répondu yigit 2016-07-12 11:24:44

, je regardais ce post pour trouver la réponse, mais... Je pense que tout le monde sur ce post était confronté au même scénario que moi: scrollToPosition() a été complètement ignoré, pour une raison évidente.

Ce que j'utilisais?

recyclerView.scrollToPosition(items.size());

... qu'est-ce que a fonctionné ?

recyclerView.scrollToPosition(items.size() - 1);
268
répondu Roc Boronat 2018-04-19 21:34:43

Je sais qu'il est tard pour répondre ici, encore si quelqu'un veut savoir que la solution est ci-dessous

conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1);
42
répondu WritingForAnroid 2017-09-11 22:27:12

Pour faire défiler de n'importe quelle position dans recyclerview vers le bas

edittext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                rv_commentList.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                      rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
                    }
                }, 1000);
            }
        });
8
répondu Muhammad Umair Shafique 2015-12-08 07:43:45

Lorsque vous appelez setAdapter, cela ne pose pas et ne positionne pas immédiatement les éléments sur l'écran (qui prend une seule passe de mise en page), d'où votre appel scrollToPosition() n'a pas d'éléments réels à faire défiler lorsque vous l'appelez.

Au lieu de cela, vous devez enregistrer un ViewTreeObserver.OnGlobalLayoutListener (via addOnGlobalLayoutListner () à partir d'un ViewTreeObserver Créé par conversationView.getViewTreeObserver()) qui retarde votre scrollToPosition() jusqu'après la première passe de mise en page:

conversationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  public void onGlobalLayout() {
    conversationView.scrollToPosition(GENERIC_MESSAGE_LIST.size();
    // Unregister the listener to only call scrollToPosition once
    conversationView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

    // Use vto.removeOnGlobalLayoutListener(this) on API16+ devices as 
    // removeGlobalOnLayoutListener is deprecated.
    // They do the same thing, just a rename so your choice.
  }
});
8
répondu ianhanniballake 2017-12-03 20:49:05
class MyLayoutManager extends LinearLayoutManager {

  public MyLayoutManager(Context context) {
    super(context, LinearLayoutManager.VERTICAL, false);
  }

  @Override public void smoothScrollToPosition(RecyclerView recyclerView,
      final RecyclerView.State state, final int position) {

    int fcvip = findFirstCompletelyVisibleItemPosition();
    int lcvip = findLastCompletelyVisibleItemPosition();

    if (position < fcvip || lcvip < position) {
      // scrolling to invisible position

      float fcviY = findViewByPosition(fcvip).getY();
      float lcviY = findViewByPosition(lcvip).getY();

      recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

        int currentState = RecyclerView.SCROLL_STATE_IDLE;

        @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

          if (currentState == RecyclerView.SCROLL_STATE_SETTLING
              && newState == RecyclerView.SCROLL_STATE_IDLE) {

            // recursive scrolling
            smoothScrollToPosition(recyclerView, state, position);
          }

          currentState = newState;
        }

        @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

          int fcvip = findFirstCompletelyVisibleItemPosition();
          int lcvip = findLastCompletelyVisibleItemPosition();

          if ((dy < 0 && fcvip == position) || (dy > 0 && lcvip == position)) {
            // stop scrolling
            recyclerView.setOnScrollListener(null);
          }
        }
      });

      if (position < fcvip) {
        // scroll up

        recyclerView.smoothScrollBy(0, (int) (fcviY - lcviY));
      } else {
        // scroll down

        recyclerView.smoothScrollBy(0, (int) (lcviY - fcviY));
      }
    } else {
      // scrolling to visible position

      float fromY = findViewByPosition(fcvip).getY();
      float targetY = findViewByPosition(position).getY();

      recyclerView.smoothScrollBy(0, (int) (targetY - fromY));
    }
  }
}

Et

MyLayoutManager layoutManager = new MyLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);

RecyclerView.Adapter adapter = new YourAdapter();
recyclerView.setAdapter(adapter);

recyclerView.smoothScrollToPosition(adapter.getItemCount() - 1);

Le code ci-dessus fonctionne, mais ce n'est pas lisse et pas cool.

4
répondu Yuki Yoshida 2014-10-28 13:45:49

Si vous avez un adaptateur attaché avec recyclerView, faites-le simplement.

mRecyclerView.smoothScrollToPosition(mRecyclerView.getAdapter().getItemCount());

4
répondu Wasim Amin 2017-05-24 13:43:48

La réponse Roc est d'une grande aide. Je voudrais y ajouter un petit bloc:

mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
2
répondu abedfar 2017-06-26 20:10:40

Cela fonctionne parfaitement pour moi:

AdapterChart adapterChart = new AdapterChart(getContext(),messageList);
recyclerView.setAdapter(adapterChart);
recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1);
2
répondu amaresh hiremani 2017-07-19 15:14:32

Ajoutez ce code après l'envoi du message et avant de recevoir le message du serveur

recyclerView.scrollToPosition(mChatList.size() - 1);
2
répondu Shubham Agrawal 2018-07-06 11:11:55

Dans mon cas où les vues n'ont pas la même hauteur, en appelant scrollToPosition sur le LayoutManager travaillé pour vraiment faire défiler vers le bas et voir pleinement le dernier élément:

recycler.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1);
1
répondu galex 2018-01-31 13:01:23

Seule la réponse de Ian a pu faire défiler mon RecyclerView jusqu'à une position spécifiée. Cependant, le RecyclerView n'a pas pu faire défiler après quand j'ai utilisé scrollToPosition(). smoothScrollToPosition() a fonctionné mais l'animation initiale l'a rendue trop lente lorsque la liste était longue. La raison en était que l'auditeur n'a pas été supprimé. J'ai utilisé le code ci-dessous pour supprimer le ViewTreeObserver et cela a fonctionné comme un charme.

    mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mRecyclerView.scrollToPosition(mPosition);
            mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });
0
répondu Anky An 2017-04-21 11:48:49

Dans Kotlin:

recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() }

private fun scrollToEnd() =
        (adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition)
0
répondu yanchenko 2018-02-04 23:28:24

Ce code vous donnera le dernier message en premier, je pense que cette réponse est utile.

    mInstaList=(RecyclerView)findViewById(R.id.insta_list);
    mInstaList.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

    mInstaList.setLayoutManager(layoutManager);
    layoutManager.setStackFromEnd(true);
    layoutManager.setReverseLayout(true);
0
répondu hasanga lakdinu 2018-04-11 03:01:24
recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.setReverseLayout(true);// Scroll to bottom
recyclerView.setLayoutManager(layoutManager);
-2
répondu LongLv 2015-12-24 09:18:53