ravi
ravi

Reputation: 2782

How to set item to center of Recycler view when selected

I am using a RecyclerView to display items horizontally. I want to set the selected item to center of the view like this

enter image description here.

This is how I am doing it:

LinearLayoutManager layoutManager
                = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(layoutManager);

Upvotes: 21

Views: 30258

Answers (5)

Ahmad
Ahmad

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

DKHirani
DKHirani

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

Paweł Kanarek
Paweł Kanarek

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:

enter image description here

Upvotes: 12

Cosmin Badulescu
Cosmin Badulescu

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

Mustansar Saeed
Mustansar Saeed

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

Related Questions