Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView - Scroll To Position Not Working Every Time

I have implemented a horizontal scrollable RecyclerView. My RecyclerView uses a LinearLayoutManager, and the problem I am facing is that when I try to use scrollToPosition(position) or smoothScrollToPosition(position) or from LinearLayoutManager's scrollToPositionWithOffset(position). Neither works for me. Either a scroll call doesn't scroll to the desired location or it doesn't invoke the OnScrollListener.

So far I have tried so many different combinations of code that I cannot post them all here. Following is the one that works for me (But only partially):

public void smoothUserScrollTo(final int position) {      if (position < 0 || position > getAdapter().getItemCount()) {         Log.e(TAG, "An attempt to scroll out of adapter size has been stopped.");         return;     }      if (getLayoutManager() == null) {         Log.e(TAG, "Cannot scroll to position a LayoutManager is not set. " +                 "Call setLayoutManager with a non-null layout.");         return;     }      if (getChildAdapterPosition(getCenterView()) == position) {         return;     }      stopScroll();      scrollToPosition(position);      if (lastScrollPosition == position) {          addOnLayoutChangeListener(new OnLayoutChangeListener() {             @Override             public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {                  if (left == oldLeft && right == oldRight && top == oldTop && bottom == oldBottom) {                     removeOnLayoutChangeListener(this);                      updateViews();                      // removing the following line causes a position - 3 effect.                     scrollToView(getChildAt(0));                 }             }         });     }      lastScrollPosition = position; }  @Override public void scrollToPosition(int position) {     if (position < 0 || position > getAdapter().getItemCount()) {         Log.e(TAG, "An attempt to scroll out of adapter size has been stopped.");         return;     }      if (getLayoutManager() == null) {         Log.e(TAG, "Cannot scroll to position a LayoutManager is not set. " +                 "Call setLayoutManager with a non-null layout.");         return;     }  //      stopScroll();          ((LinearLayoutManager) getLayoutManager()).scrollToPositionWithOffset(position, 0); //        getLayoutManager().scrollToPosition(position);     } 

I opted for scrollToPositionWithOffset() because of this but the case perhaps is different as I use a LinearLayoutManager instead of GridLayoutManager. But the solution does work for me too, but as I said earlier only partially.

  • When the call to scroll is from 0th position to totalSize - 7 scroll works like a charm.
  • When scroll is from totalSize - 7 to totalSize - 3, First time I only scroll to 7th last item in the list. The second time however I can scroll fine
  • When scrolling from totalSize - 3 to totalSize, I start getting unexpected behavior.

If anyone has found a work around I'd Appreciate it. Here's the gist to my code of custom ReyclerView.

like image 293
Abbas Avatar asked Apr 05 '16 12:04

Abbas


Video Answer


2 Answers

I had the same issue some weeks ago, and found only a really bad solution to solve it. Had to use a postDelayed with 200-300ms.

new Handler().postDelayed(new Runnable() {     @Override     public void run() {         yourList.scrollToPosition(position);     } }, 200); 

If you found a better solution, please let me know! Good luck!

like image 185
Robert Banyai Avatar answered Sep 28 '22 12:09

Robert Banyai


Turns out I was having a similar issue until I utilized

myRecyclerview.scrollToPosition(objectlist.size()-1) 

It would always stay at the top when only putting in the objectlist size. This was until i decided to set the size equal to a variable. Again, that didn't work. Then I assumed that perhaps it was handling an outofboundsexception without telling me. So I subtracted it by 1. Then it worked.

like image 31
Stefan Petit-Freres Avatar answered Sep 28 '22 13:09

Stefan Petit-Freres