Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically snap to position on Recycler view with LinearSnapHelper

Tags:

android

I have implemented a horizontal recyclerView with LinearSnapHelper, to implement a UI input that selects a particular configuration. Kinda like the old school number picker/selector or spinner. The item in the center is the selected position.

it works fine and all, but here's the problem. On initial start up, I need to programmatically set the position of the recycler view such that the selected item (the index of which was loaded from disk) is position in the center.

.scrollToPosition() wont work becuase it places the selected item in the begining.

now I know I can do all the math and calculate the x coordinate and manually set it, but thats a lot of redundant work because LinearSnapHelper is already doing this, and I feel like there should be a way to just reuse that logic, but with actually initiating a fling.

I need something like LinearSnapHelper.snapToPosition()

like image 418
Siavash Avatar asked Mar 23 '17 22:03

Siavash


2 Answers

More general solution:

  1. First scroll RecyclerView to make target item visible.
  2. Than, take the object of target View and use SnapHelper to determine distance for the final snap.
  3. Finally scroll to target position.

NOTE: This works only because programmatically you are scrolling at the exact position & covering the missing distance by exact value using scrollBy instead of doing smooth scrolling

Code snippet:

mRecyclerView.scrollToPosition(selectedPosition);
mRecyclerView.post(() -> {
        View view = mLayoutManager.findViewByPosition(selectedPosition);
        if (view == null) {
            Log.e(WingPickerView.class.getSimpleName(), "Cant find target View for initial Snap");
            return;
        }

        int[] snapDistance = mSnapHelper.calculateDistanceToFinalSnap(mLayoutManager, view);
        if (snapDistance[0] != 0 || snapDistance[1] != 0) {
            mRecyclerView.scrollBy(snapDistance[0], snapDistance[1]);
        }
    }
});
like image 78
donaldTheDuck Avatar answered Nov 14 '22 22:11

donaldTheDuck


Try calling smoothScrollToPosition on the RecyclerView object, and passing the position index (int)

mRecyclerView.smoothScrollToPosition(position);

Worked for me with a LinearLayoutManager and LinearSnapHelper. It animates the initial scroll, but at least snaps the item in position.

This is my first post on the stack, hope it helps :)

like image 3
Miro Avatar answered Nov 14 '22 21:11

Miro