This questions seems so simple, in fact Android SDK has provided several API to scroll item at certain position.
fun iJustWantToScroll() {
recyclerView.scrollToPosition()
recyclerView.smoothScrollToPosition()
recyclerView.layoutManager?.scrollToPosition()
(recyclerView.layoutManager as LinearLayoutManager).scrollToPositionWithOffset()
}
It should work as expected right? Afterall, scrolling an item to certain position is a fairly common usage. Yet, why does this question is still popular?
Me too, is a victim of this bug. I have spent years before I realised I was asking the wrong question, before I'll answer this question, let me show you what I previously had done before.
fun iJustWantToScroll() {
recyclerView.postDelayed(Runnable {
// or use other API
recyclerView.smoothScrollToPosition(0)
// give a delay of one second
}, 1_000)
}
This is a bit hacky, but always works (in my scenario). Try to reduce the delay, usually 500 milliseconds is enough.
The right question to ask about scrollToPosition
is not How, but When.
When to scroll RecyclerView to a certain position?
I find that the problem why scrollToPosition
, and others API, does not work is because the dataset is not yet ready. We should call scrollToPosition
when the recyclerView has received dataset. To do that, we can use AdapterDataObserver
.
AdapterDataObserver on d.android
AdapterDataObserver
has five public methods.
As the method name implies, onItemRangeInserted
is called when an item is added to the RecyclerView, and onItemRemoved
is called when an item is removed from the RecyclerView.
There is an exception for onChanged
. onChanged
is only called when you call notify
on an Adapter, it is not going to called everytime there is a change on the RecyclerView.
I usually call scrollToPosition
when the dataset is succesfully inserted to a RecyclerView, for example:
adapter.registerAdapterDataObserver( object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(
positionStart: Int,
itemCount: Int
) {
recyclerView.scrollToPosition(0)
}
override fun onItemRangeRemoved(
positionStart: Int,
itemCount: Int
) {
recyclerView.smoothScrollToPosition(itemCount)
}
}
This way, we don't have to wait certain millisecond to scroll a ReyclerView. When there is a new dataset, we can trigger scrollToPosition
or smoothScrollToPosition
and be sure RecyclerView is scrolled.
Latest comments (5)
good article, m question how we should store the recyclerview position in background
perfect! thanks
OOOooooo thanks!
Saved me !!
Very interesting, Thanks