Reputation: 694
I want to scroll to a particular item in my RecyclerView, but using LinearLayoutManager.scrollToPosition(position: Int)
, the item is sometimes at the top of the screen and sometimes at the bottom.
I want it to scroll to this item and place it at the center of the screen.
I can achieve this with a smooth scroller using other answers, but I often want to jump very far in the list, so waiting for the smooth scroll to complete is unacceptable.
Upvotes: 0
Views: 2398
Reputation: 694
I found many answers for achieving this with a smooth scroller, but in case you want to achieve this without smooth scrolling (to immediately jump a large distance for example), you can do it with a normal LinearLayoutManager/GridLayoutManager by calculating the offset yourself.
I subclassed LinearLayoutManager so that I could just use the scrollToPosition function and have it always scroll to that position with the item in the center, but you can just use the scrollToPositionWithOffset function of the LinearLayoutManager with a manual offset each time if you prefer.
class CenterScrollLayoutManager(context: Context, orientation: Int, reverseLayout: Boolean): LinearLayoutManager(context, orientation, reverseLayout) {
override fun scrollToPosition(position: Int) {
//this will place the top of the item at the center of the screen
val height = getApplicationContext().resources.displayMetrics.heightPixels
val offset = height/2
//if you know the item height, you can place the center of the item at the center of the screen
// by subtracting half the height of that item from the offset:
// val height = getApplicationContext().resources.displayMetrics.heightPixels
// //(say item is 40dp tall)
// val itemHeight = 40F * getApplicationContext().resources.displayMetrics.scaledDensity
// val offset = height/2 - itemHeight/2
//depending on if you have a toolbar or other headers above the RecyclerView,
// you may want to subtract their height as well:
// val height = getApplicationContext().resources.displayMetrics.heightPixels
// //(say item is 40dp tall):
// val itemHeight = 40F * getApplicationContext().resources.displayMetrics.scaledDensity
// //(say toolbar is 56dp tall, which is the default action bar height for portrait mode)
// val toolbarHeight = 56F * getApplicationContext().resources.displayMetrics.scaledDensity
// val offset = height/2 - itemHeight/2 - toolbarHeight
//call scrollToPositionWithOffset with the desired offset
super.scrollToPositionWithOffset(position, offset)
}
}
Then, to use it, you need to first set this as the layout manager for your RecyclerView, likely inside OnCreate (if in an activity) or OnViewCreated (if in a fragment):
yourRecyclerView.apply {
adapter = yourRecyclerViewAdapter
layoutManager = CenterScrollLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
Then, just scroll to a desired position, and the item should be in the center:
yourRecyclerView.scrollToPosition(desiredPosition)
This also works with a GridLayoutManager.
Upvotes: 3