androidandroid-recyclerviewsnapping

Snapping in horizontal recycler view


I have a horizontal Recycler View and I want to enable snapping in it. I read some of the threads on SO and found this code to be working very well. I don't have much knowledge about the internal workings of Recycler View and Layout Managers so wanted to ask if the code can be modified to:

  1. No matter what the velocity of fling, I want to move only one item forward or backward.

  2. The snapping speed is slow. If I move the view more than half the width, the next item comes into center but very slowly. Can this be increased so that the snap is instant?

Any ideas on how to achieve the above behaviors would be highly helpful.


Solution

  • Finally figured it out with some help from other codes:

    public class FlingRecyclerView extends RecyclerView {
    
        int screenWidth;
    
        public FlingRecyclerView(Context context) {
            super(context);
            WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            screenWidth = size.x;
        }
    
        public FlingRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            screenWidth = size.x;
        }
    
        public FlingRecyclerView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
            Display display = windowManager.getDefaultDisplay();
            Point size = new Point();
            display.getSize(size);
            screenWidth = size.x;
        }
    
        @Override
        public boolean fling(int velocityX, int velocityY) {
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) getLayoutManager();
    
    //these four variables identify the views you see on screen.
            int lastVisibleView = linearLayoutManager.findLastVisibleItemPosition();
            int firstVisibleView = linearLayoutManager.findFirstVisibleItemPosition();
            View firstView = linearLayoutManager.findViewByPosition(firstVisibleView);
            View lastView = linearLayoutManager.findViewByPosition(lastVisibleView);
    
    //these variables get the distance you need to scroll in order to center your views.
    //my views have variable sizes, so I need to calculate side margins separately.
    //note the subtle difference in how right and left margins are calculated, as well as
    //the resulting scroll distances.
    
    
            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(user swipes to the left)
            if (velocityX > 0) smoothScrollBy(scrollDistanceLeft, 0);
            else smoothScrollBy(-scrollDistanceRight, 0);
    
            return true;
        }
    }
    

    Works awesome for my requirements. Hope it helps someone else too.