Recyclerview not scrolling to end when keyboard opens

AndroidListviewAndroid RecyclerviewAndroid Softkeyboard

Android Problem Overview


I am using recylerview in my application and whenever new element is added to recyclerview, it scrolls to last element by using

recyclerView.scrollToPosition(adapter.getCount());

But, whenever keyboard opens(because of editTextView), it resizes the view and recyclerview gets smaller, but couldn't scroll to last element.

android:windowSoftInputMode="adjustResize"

I even tried to used the following code to scroll to last element, but it didn't work

editTextView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus){
                recyclerView.scrollToPosition(chatAdapter.getItemCount());
            }
        }
    });

I can try adjustPan to shift the pan up, but it is hiding my toolbar. Please suggest any way to rectify the issue.

Android Solutions


Solution 1 - Android

You can catch keyboard up changes using recyclerview.addOnLayoutChangeListener(). If bottom is smaller than oldBottom then keyboard is in up state.

if ( bottom < oldBottom) { 
   recyclerview.postDelayed(new Runnable() { 
       @Override 
       public void run() {
           recyclerview.smoothScrollToPosition(bottomPosition); 
       }
    }, 100);
}

Solution 2 - Android

Add this your activity or fragment:

	if (Build.VERSION.SDK_INT >= 11) {
		recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
			@Override
			public void onLayoutChange(View v,
					int left, int top, int right, int bottom,
					int oldLeft, int oldTop, int oldRight, int oldBottom) {
				if (bottom < oldBottom) {
					recyclerView.postDelayed(new Runnable() {
						@Override
						public void run() {
							recyclerView.smoothScrollToPosition(
                                    recyclerView.getAdapter().getItemCount() - 1);
						}
					}, 100);
				}
			}
		});
	}

Solution 3 - Android

It works for me

LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(layoutManager);

Solution 4 - Android

I found the postDelayed to be unnecessary and using adapter positions doesn't account for when the recycler is scrolled to somewhere in the middle of an item. I achieved the look I wanted with this:

recycler.addOnLayoutChangeListener((view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
    if (bottom < oldBottom) {
        messageRecycler.scrollBy(0, oldBottom - bottom);
    }
})

Solution 5 - Android

Although this an old question, I experienced this problem today and I found out that none of of the above method works. This is my solution

    recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v,
                                   int left, int top, int right, int bottom,
                                   int oldLeft, int oldTop, int oldRight, int oldBottom) {
            if (bottom < oldBottom) {
                final int lastAdapterItem = mAdapter.getItemCount() - 1;
                recyclerView.post(new Runnable() {
                  @Override
                  public void run() {
                    int recyclerViewPositionOffset = -1000000;
                    View bottomView = linearLayoutManager.findViewByPosition(lastAdapterItem);
                    if (bottomView != null) {
                       recyclerViewPositionOffset = 0 - bottomView.getHeight();
                     }
                     linearLayoutManager.scrollToPositionWithOffset(lastAdapterItem, recyclerViewPositionOffset);
                  }
                });
              }
         });
   }

Solution 6 - Android

This works.

private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private LinearLayoutManager mManager;

...

mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);

(initialize and set adapter.)

mRecyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        if (bottom < oldBottom) scrollToBottom();
    }
});

private void scrollToBottom() {
    mManager.smoothScrollToPosition(mRecyclerView, null, mAdapter.getItemCount());
}

Solution 7 - Android

        recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount());

Solution 8 - Android

It works properly in support library version 27.0.1

There is nothing to set in the manifest.

val currentScrollPosition = 0

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
            super.onScrolled(recyclerView, dx, dy)

            currentScrollPosition = recyclerView.computeVerticalScrollOffset() + recyclerView.computeVerticalScrollExtent()
        }

        override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) { }
    })

    storyList.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
        if (bottom < oldBottom) {
            if (currentScrollPosition >= recyclerView.computeVerticalScrollRange()) {
                recyclerVIew.post {
                    recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_NEVER
                    recyclerView.smoothScrollBy(0, recyclerView.computeVerticalScrollRange() - recyclerView.computeVerticalScrollOffset() + recyclerView.computeVerticalScrollExtent())
                }
            }
        } else {
            recyclerView.overScrollMode = RecyclerView.OVER_SCROLL_ALWAYS
        }
    }

Solution 9 - Android

layoutManager.scrollToPositionWithOffset(chatMessageAdapter.getItemCount() - 1, 0);

Solution 10 - Android

You can use addOnItemTouchListener to see the scrolling change:

private Boolean scrollListerActivate = true;

mRecyclerViewTop.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        if(scrollListerActivate == true) {
            scrollListTopManager();
        }
    }
});

To scroll for last (or other) position you should use scrollListTopManager method:

public void scrollListTopManager() {
    int position = 0;
    int itemCount = mRecyclerViewTop.getAdapter().getItemCount();
    position = itemCount - 1;
    
    mRecyclerViewTop.scrollToPosition(position);
}

You should also use addOnItemTouchListener to stop using scrollListTopManager method, if you want to scroll manually:

mRecyclerViewTop.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent 
    motionEvent) {
        scrollListerActivate = false;
        return false;
    }
    @Override
    public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) 
    {}
            
    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean b) {}
});

Solution 11 - Android

Bind the RecyclerView inside NestedScrollView

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</android.support.v4.widget.NestedScrollView>


 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMukesh SharmaView Question on Stackoverflow
Solution 1 - Androidjihoon kimView Answer on Stackoverflow
Solution 2 - AndroidmutkanView Answer on Stackoverflow
Solution 3 - AndroidanisartView Answer on Stackoverflow
Solution 4 - Androidmp501View Answer on Stackoverflow
Solution 5 - AndroidKutae ShawView Answer on Stackoverflow
Solution 6 - AndroidwonsucView Answer on Stackoverflow
Solution 7 - Androidsdelvalle57View Answer on Stackoverflow
Solution 8 - Androidminjung AhnView Answer on Stackoverflow
Solution 9 - AndroidRamesh RView Answer on Stackoverflow
Solution 10 - AndroidBorys DrausView Answer on Stackoverflow
Solution 11 - AndroidKarthikeyanView Answer on Stackoverflow