Reputation: 2782
I am using a RecyclerView
to display items horizontally. I want to set the selected item to center of the view like this
This is how I am doing it:
LinearLayoutManager layoutManager
= new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
Upvotes: 21
Views: 30258
Reputation: 76
Define your custom layout manager as
class CenterLayoutManager : LinearLayoutManager {
constructor(context: Context) : super(context)
constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State, position: Int) {
val centerSmoothScroller = CenterSmoothScroller(recyclerView.context)
centerSmoothScroller.targetPosition = position
startSmoothScroll(centerSmoothScroller)
}
private class CenterSmoothScroller(context: Context) : LinearSmoothScroller(context) {
override fun calculateDtToFit(viewStart: Int, viewEnd: Int, boxStart: Int, boxEnd: Int, snapPreference: Int): Int = (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2)
}
}
Then assign this layout manager to your recycler view
myRecyclerview.layoutManager =
CenterLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
In recyclerview's item onClick method use
myRecyclerview.smoothScrollToPosition(position)
where position should get from onBindViewHolder
Also use LinearSnapHelper as
val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(myRecyclerview)
it will controll scrolling effectively
Also attatch scroll listner to recyclerview to get item at center position
Recyclerview.setOnScrollListener(object:
RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
var view=recyclerView[0]
}
})
check out this stackoverflow answer for more details
Upvotes: 2
Reputation: 126
You can achieve the same output with minimal lines of code. Where, view is view of selected adapter item and StaticData.SCREEN_WIDTH is device width.
View view = rvCategory.getChildAt(pos);
if (view == null)
return;
int scrollX = (view.getLeft() - (StaticData.SCREEN_WIDTH / 2)) + (view.getWidth() / 2);
rvCategory.smoothScrollBy(scrollX, 0);
Upvotes: 5
Reputation: 2626
To obtain middle item on your screen from RecyclerView you can attach OnScrollListener to RecyclerView and inside listener you should get position of current items then you should check if area of given item is on middle of screen.
Code sample in Kotlin:
// Attach OnScrollListener to your RecyclerView
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
recyclerView.post {
selectMiddleItem()
}
}
})
// implementation of method that is called from OnScrollListener
private fun selectMiddleItem() {
val firstVisibleIndex = layoutManager.findFirstVisibleItemPosition()
val lastVisibleIndex = layoutManager.findLastVisibleItemPosition()
val visibleIndexes = listOf(firstVisibleIndex..lastVisibleIndex).flatten()
for (i in visibleIndexes) {
val vh = findViewHolderForLayoutPosition(i)
if (vh?.itemView == null) {
continue
}
val location = IntArray(2)
vh.itemView.getLocationOnScreen(location)
val x = location[0]
val halfWidth = vh.itemView.width * .5
val rightSide = x + halfWidth
val leftSide = x - halfWidth
val isInMiddle = screenWidth * .5 in leftSide..rightSide
if (isInMiddle) {
// "i" is your middle index and implement selecting it as you want
// optionsAdapter.selectItemAtIndex(i)
return
}
}
}
And as result you should get something like this:
Upvotes: 12
Reputation: 235
This is for snapping the item in the center when scrolling, or when clicking on an ite.
You need to have a SnapHelper added to the RecyclerView. Here is how:
final RecyclerView recyclerViewObject = view.findViewById(R.id.recyclerViewObjectId);
final LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerViewObject);
recyclerViewObject.setOnFlingListener(snapHelper);
then you just call this code
recyclerViewObject.addOnItemTouchListener(
new RecyclerItemClickListener(getContext(), recyclerViewObject ,new RecyclerItemClickListener.OnItemClickListener() {
@Override public void onItemClick(View view, int position) {
recyclerViewObject.smoothScrollToPosition(position);
}
@Override public void onLongItemClick(View view, int position) {
}
})
);
Upvotes: 8
Reputation: 2790
Please try sort of this solution:
LinearLayoutManager layoutManager = ((LinearLayoutManager)recyclerView.getLayoutManager());
int totalVisibleItems = layoutManager.findLastVisibleItemPosition() - layoutManager.findFirstVisibleItemPosition()
int centeredItemPosition = totalVisibleItems / 2;
recyclerView.smoothScrollToPosition(position);
recyclerView.setScrollY(centeredItemPosition );
Hope this helps.
Upvotes: 3