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 avoir chargé 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) 

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

setStackFromEnd=true simplement setStackFromEnd=true ou setReverseLayout=true pour que LLM setReverseLayout=true éléments de la fin.

La différence entre ces deux éléments est que setStackFromEnd définira la vue pour afficher le dernier élément, la direction de la disposition restra la même. (Donc, dans une vue recyclée horizontale de gauche à droite, le dernier élément sera affiché et le défilement vers la gauche affichera les éléments précédents)

Considérant que setReverseLayout changera l’ordre des éléments ajoutés par l’adaptateur. La mise en page commencera à partir du dernier élément, qui sera le plus à gauche dans une vue de recyclage de LTR, puis le défilement à droite affichera les éléments précédents.

Échantillon:

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

Voir la documentation pour plus de détails.

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() était complètement ignoré, pour une raison évidente.

Qu’est-ce que j’utilisais?

 recyclerView.scrollToPosition(items.size()); 

… ce qui a fonctionné?

 recyclerView.scrollToPosition(items.size() - 1); 

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

 conversationView.smoothScrollToPosition(conversationView.getAdapter().getItemCount() - 1); 

Lorsque vous appelez setAdapter , qui ne dépose pas et ne positionne pas immédiatement les éléments à l’écran (qui ne nécessitent qu’une seule passe de mise en page), votre appel scrollToPosition() ne contient aucun élément réel à atteindre 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’à ce que le premier passage 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. } }); 

Pour faire défiler vers le bas depuis n’importe quelle position de la liste de recyclage

 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); } }); 
 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.

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

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

La réponse de Roc est une grande aide. Je voudrais y append un petit bloc:

 mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1); 

Cela fonctionne parfaitement bien pour moi:

 AdapterChart adapterChart = new AdapterChart(getContext(),messageList); recyclerView.setAdapter(adapterChart); recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount()-1); 

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

 recyclerView.scrollToPosition(mChatList.size() - 1); 

Dans mon cas où les vues n’ont pas la même hauteur, l’appel de scrollToPosition sur le LayoutManager a fonctionné pour atteindre le fond et voir le dernier élément:

 recycler.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1); 

Seule la réponse de Ian a été capable de faire défiler mon RecyclerView à une position spécifiée. Cependant, le RecyclerView n’a pas pu faire défiler après avoir utilisé scrollToPosition() . smoothScrollToPosition() fonctionné mais l’animation initiale l’a rendu trop lent lorsque la liste était longue. La raison était que l’auditeur n’avait pas été enlevé. J’ai utilisé le code ci-dessous pour supprimer l’actuel 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); } }); 

À Kotlin:

 recyclerView.viewTreeObserver.addOnGlobalLayoutListener { scrollToEnd() } private fun scrollToEnd() = (adapter.itemCount - 1).takeIf { it > 0 }?.let(recyclerView::smoothScrollToPosition) 

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); 
 recyclerView.setHasFixedSize(true); LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); layoutManager.setReverseLayout(true);// Scroll to bottom recyclerView.setLayoutManager(layoutManager);