Search code examples
androidandroid-fragmentsandroid-viewpagersmooth-scrolling

Android: Viewpager does not smooth scroll


I have a ViewPager and I want it to smooth scroll by calling viewPager.setCurrentItem(index, true). The ViewPager consists of fragments which have RecyclerView inside them.

I call setCurrentItem when the user swipes right or left on the header of the fragment and then view pager shall scroll to the next item. But the problem is that the view pager does not (every time) smooth scroll to the next fragment. I have tried some solutions that I found here but non did really work.

Strangely sometimes (mostly when I go from right to left) it does smooth scroll but mostly it doesn't work.

EDIT:

Here is my code:

ViewPagerFragment:

...

private void setViews(){
    header.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
        public void onSwipeRight() {
            swipeRight();
        }
        public void onSwipeLeft() {
            swipeLeft();
        }
    });
}

private void swipeLeft(){
    final CustomSwipeViewPager viewPager = (CustomSwipeViewPager) getActivity().findViewById(R.id.list_view_pager);
    final int currentItem = viewPager.getCurrentItem();
    if(currentItem < 4){
        Thread sepThread = new Thread(new Runnable(){

            public void run()
            {
                //Then, inside that thread, run a runnable on the ui thread.
                //MyActivity.getContext() is a static function that returns the
                //context of the activity. It's us.getContext()eful in a pinch.
                getActivity().runOnUiThread(new Runnable(){

                    @Override
                    public void run() {

                        viewPager.setCurrentItem(currentItem + 1, true);

                    }

                });

            }
        });


        sepThread.start();
    }
}

private void swipeRight(){
    final CustomSwipeViewPager viewPager = (CustomSwipeViewPager) getActivity().findViewById(R.id.list_view_pager);
    final int currentItem = viewPager.getCurrentItem();
    if(currentItem > 0){
        Thread sepThread = new Thread(new Runnable(){

            public void run()
            {
                getActivity().runOnUiThread(new Runnable(){

                    @Override
                    public void run() {

                        viewPager.setCurrentItem(currentItem - 1, true);

                    }

                });

            }
        });


        sepThread.start();
    }
}

...

Custom Touch Listener:

public class OnSwipeTouchListener implements OnTouchListener {

private final GestureDetector gestureDetector;

public OnSwipeTouchListener (Context ctx){
    gestureDetector = new GestureDetector(ctx, new GestureListener());
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
}

private final class GestureListener extends SimpleOnGestureListener {

    private static final int SWIPE_THRESHOLD = 100;
    private static final int SWIPE_VELOCITY_THRESHOLD = 100;

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

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        boolean result = false;
        try {
            float diffY = e2.getY() - e1.getY();
            float diffX = e2.getX() - e1.getX();
            if (Math.abs(diffX) > Math.abs(diffY)) {
                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffX > 0) {
                        onSwipeRight();
                    } else {
                        onSwipeLeft();
                    }
                    result = true;
                }
            }
            else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                if (diffY > 0) {
                    onSwipeBottom();
                } else {
                    onSwipeTop();
                }
                result = true;
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return result;
    }
}

public void onSwipeRight() {
}

public void onSwipeLeft() {
}

public void onSwipeTop() {
}

public void onSwipeBottom() {
}

}

I hope this is all you need.


Solution

  • I found out why the ViewPager does not scroll smoothly every time. It seems like the creation of the of the single Fragments inside the ViewPager takes too long and that is why the ViewPager does not scroll smoothly every time. It may scroll smoothly, because the fragments have been already initialized, but that is not always the case.

    Seems like I have to make the creation of the fragments faster.