0

I have a simple activity which has a root layout.The root layout contains a recyclerview. Recyclerview will contain 20 items created from items.xml , which consists of 3 text views.Here items.xml represent single item in the recyclerview.

The recycler view can be scrolled both the ways , it is kind a loop of the items between 1 to 20.

I have a requirement to smoothscroll only 4 items , irrespective of the velocity of the swipe/fling.

Approaches which i have tried many approaches but coudn't succeed till now. If anyone can give any suggestions , that would be very helpful.

  1. SnapHelper - this seems to snap only the item which is in the center.

  2. Using gesture detector - the gestures are getting detected for all the actions , but i am unable to prevent the recyclerview's default scrolling behaviour.

The main issue is the over-scrolling of recycler view due to varing velocities of user scrolls and flings.

Here is my set up for the gesture detector.

public myRecyclerTouchListner(final Context context, final RecyclerView recycleView,
                                                     final LinearLayoutManager linearLayoutManager,
                                                     final ClickListener clicklistener){


            final ViewConfiguration vc = ViewConfiguration.get(context);
            final int swipeMinDistance = vc.getScaledPagingTouchSlop();
            final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity();
            final int swipeMaxOffPath = vc.getScaledTouchSlop();

            this.clicklistener=clicklistener;
            simpleGestureDetector =new GestureDetector(context,new GestureDetector.SimpleOnGestureListener( ){
                @Override
                public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                    Log.d("try", "on Fling called");
                    if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE &&
                            Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                        //From Right to Left
                        recycleView.smoothScrollToPosition(linearLayoutManager.
                                findLastCompletelyVisibleItemPosition() + Constants.spanLength);
                        return true;
                    }  else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE &&
                            Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                        //From Left to Right
                        recycleView.smoothScrollToPosition(linearLayoutManager.
                                findFirstCompletelyVisibleItemPosition() - Constants.spanLength);
                        return true;
                    }

                    return true;
                }

                @Override
                public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {


                    return true;
                }
                @Override
                public boolean onSingleTapUp(MotionEvent e) {
                    return false;
                }

                @Override
                public boolean onDown(MotionEvent e) {
                    return true;
                }

                @Override
                public boolean onDoubleTap(MotionEvent e) {
                    return true;
                }
                @Override
                public void onLongPress(MotionEvent e) {
                    Log.d("Try", "Long press gesture");

                    View child=recycleView.findChildViewUnder(e.getX(),e.getY());
                    if(child!=null && clicklistener!=null){
                        clicklistener.onLongClick(child,recycleView.getChildAdapterPosition(child));
                    }
                }
            });
MeLean
  • 3,092
  • 6
  • 29
  • 43

2 Answers2

0

I think your problem is that scrolling is starting from last visible position where Fling is detected and that mess up the things.

Try with global variable for example int lastScrolledPosition = 0;.

And OnFling recycleView.smoothScrollToPosition(lastScrolledPosition + Constants.spanLength);

I thing this should do the trick. You should change if lastScrolledPosition < Recycleritems count.

MeLean
  • 3,092
  • 6
  • 29
  • 43
  • Hi MeLine , thanks for ur answer , actually I have already implemented the same logic as u suggested , but the issue is recycle view gets over scrolled due to the varing velocity of the swipe , I want to change that behaviour. – Sankalp Pandya Jan 14 '18 at 19:07
0

It turns out I had to use Snaphelper for custom scroll behavior in case wherein I need control over programmatic scroll and user-scroll(fling).

This was exactly what I was looking for: How to snap RecyclerView items so that every X items would be considered like a single unit to snap to?

I hope it will be helpful :)