Skip to content

Instantly share code, notes, and snippets.

@nesquena
Last active June 21, 2023 23:04
Show Gist options
  • Select an option

  • Save nesquena/b26f9a253bbbb6a2e4890891e8a57eb9 to your computer and use it in GitHub Desktop.

Select an option

Save nesquena/b26f9a253bbbb6a2e4890891e8a57eb9 to your computer and use it in GitHub Desktop.

Revisions

  1. nesquena revised this gist Jul 30, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions SnappyRecyclerView.java
    Original file line number Diff line number Diff line change
    @@ -16,10 +16,10 @@ public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int def
    super(context, attrs, defStyle);
    }

    // Returns the currently snapped item
    // Returns the currently snapped item position
    public int getFirstVisibleItemPosition() {
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
    return linearLayoutManager.findLastVisibleItemPosition();
    return linearLayoutManager.findFirstCompletelyVisibleItemPosition();
    }

    @Override
  2. nesquena revised this gist Jul 29, 2016. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions SnappyRecyclerView.java
    Original file line number Diff line number Diff line change
    @@ -15,6 +15,12 @@ public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs) {
    public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    }

    // Returns the currently snapped item
    public int getFirstVisibleItemPosition() {
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
    return linearLayoutManager.findLastVisibleItemPosition();
    }

    @Override
    public boolean fling(int velocityX, int velocityY) {
  3. nesquena revised this gist Jul 29, 2016. No changes.
  4. nesquena revised this gist Jul 29, 2016. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions SnappyRecyclerView.java
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    // From: http://stackoverflow.com/a/37816976
    public class SnappyRecyclerView extends RecyclerView {

    // Use it with a horizontal LinearLayoutManager
  5. nesquena revised this gist Jul 29, 2016. No changes.
  6. nesquena created this gist Jul 29, 2016.
    107 changes: 107 additions & 0 deletions SnappyRecyclerView.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,107 @@
    public class SnappyRecyclerView extends RecyclerView {

    // Use it with a horizontal LinearLayoutManager
    // Based on http://stackoverflow.com/a/29171652/4034572

    public SnappyRecyclerView(Context context) {
    super(context);
    }

    public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    }

    public SnappyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    }

    @Override
    public boolean fling(int velocityX, int velocityY) {

    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();

    int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;

    // views on the screen
    int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
    View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
    int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
    View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

    // distance we need to scroll
    int leftMargin = (screenWidth - lastView.getWidth()) / 2;
    int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
    int leftEdge = lastView.getLeft();
    int rightEdge = firstView.getRight();
    int scrollDistanceLeft = leftEdge - leftMargin;
    int scrollDistanceRight = rightMargin - rightEdge;

    if (Math.abs(velocityX) < 1000) {
    // The fling is slow -> stay at the current page if we are less than half through,
    // or go to the next page if more than half through

    if (leftEdge > screenWidth / 2) {
    // go to next page
    smoothScrollBy(-scrollDistanceRight, 0);
    } else if (rightEdge < screenWidth / 2) {
    // go to next page
    smoothScrollBy(scrollDistanceLeft, 0);
    } else {
    // stay at current page
    if (velocityX > 0) {
    smoothScrollBy(-scrollDistanceRight, 0);
    } else {
    smoothScrollBy(scrollDistanceLeft, 0);
    }
    }
    return true;

    } else {
    // The fling is fast -> go to next page

    if (velocityX > 0) {
    smoothScrollBy(scrollDistanceLeft, 0);
    } else {
    smoothScrollBy(-scrollDistanceRight, 0);
    }
    return true;

    }

    }

    @Override
    public void onScrollStateChanged(int state) {
    super.onScrollStateChanged(state);

    // If you tap on the phone while the RecyclerView is scrolling it will stop in the middle.
    // This code fixes this. This code is not strictly necessary but it improves the behaviour.

    if (state == SCROLL_STATE_IDLE) {
    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();

    int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;

    // views on the screen
    int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
    View lastView = linearLayoutManager.findViewByPosition(lastVisibleItemPosition);
    int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
    View firstView = linearLayoutManager.findViewByPosition(firstVisibleItemPosition);

    // distance we need to scroll
    int leftMargin = (screenWidth - lastView.getWidth()) / 2;
    int rightMargin = (screenWidth - firstView.getWidth()) / 2 + firstView.getWidth();
    int leftEdge = lastView.getLeft();
    int rightEdge = firstView.getRight();
    int scrollDistanceLeft = leftEdge - leftMargin;
    int scrollDistanceRight = rightMargin - rightEdge;

    if (leftEdge > screenWidth / 2) {
    smoothScrollBy(-scrollDistanceRight, 0);
    } else if (rightEdge < screenWidth / 2) {
    smoothScrollBy(scrollDistanceLeft, 0);
    }
    }
    }

    }