there is also a simple way to do it
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1)) {
Toast.makeText(YourActivity.this, "Last", Toast.LENGTH_LONG).show();
}
}
});
direction integers: -1 for up, 1 for down, 0 will always return false.
Use this code for avoiding repeated calls
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(1) && newState==RecyclerView.SCROLL_STATE_IDLE) {
Log.d("-----","end");
}
}
});
Just implement a addOnScrollListener() on your recyclerview. Then inside the scroll listener implement the code below.
RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (mIsLoading)
return;
int visibleItemCount = mLayoutManager.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int pastVisibleItems = mLayoutManager.findFirstVisibleItemPosition();
if (pastVisibleItems + visibleItemCount >= totalItemCount) {
//End of list
}
}
};
Answer is in Kotlin, it will work in Java. IntelliJ should convert it for you if you copy and paste.
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener(){
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
// 3 lines below are not needed.
Log.d("TAG","Last visible item is: ${gridLayoutManager.findLastVisibleItemPosition()}")
Log.d("TAG","Item count is: ${gridLayoutManager.itemCount}")
Log.d("TAG","end? : ${gridLayoutManager.findLastVisibleItemPosition() == gridLayoutManager.itemCount-1}")
if(gridLayoutManager.findLastVisibleItemPosition() == gridLayoutManager.itemCount-1){
// We have reached the end of the recycler view.
}
super.onScrolled(recyclerView, dx, dy)
}
})
This will also work for LinearLayoutManager
because it has the same methods used above. Namely findLastVisibleItemPosition()
and getItemCount()
(itemCount
in Kotlin).
I was not getting a perfect solution by the above answers because it was triggering twice even on onScrolled
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
if( !recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN))
context?.toast("Scroll end reached")
}
Alternative solution which I had found some days ago,
rv_repatriations.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (!recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN) && recyclerView.scrollState == RecyclerView.SCROLL_STATE_IDLE
&& !isLoaded
) {
isLoaded = true
//do what you want here and after calling the function change the value of boolean
Log.e("RepatriationFragment", "Scroll end reached")
}
}
})
Using a boolean to ensure that it's not called multiple times when we hit the bottom.
After not being satisfied with most the other answers in this thread, I found something I think is better and is not anywhere on here.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (!recyclerView.canScrollVertically(1) && dy > 0)
{
//scrolled to BOTTOM
}else if (!recyclerView.canScrollVertically(-1) && dy < 0)
{
//scrolled to TOP
}
}
});
This is simple and will hit exactly one time under all conditions when you have scrolled to the top or bottom.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With