Changing the speed of transition of ViewPager and setCurrentItem

android, android-pagetransformer, android-viewpager

Solution

Use this Custom `View`

public class ViewPagerCustomDuration extends ViewPager {
    private FixedSpeedScroller mScroller = null;

    public ViewPagerCustomDuration(Context context) {
        super(context);
        init();
    }

    public ViewPagerCustomDuration(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /*
     * Override the Scroller instance with our own class so we can change the
     * duration
     */
    private void init() {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            mScroller = new FixedSpeedScroller(getContext(),
                    new DecelerateInterpolator());
            scroller.set(this, mScroller);
        } catch (Exception ignored) {
        }
    }

    /*
     * Set the factor by which the duration will change
     */
    public void setScrollDuration(int duration) {
        mScroller.setScrollDuration(duration);
    }

    private class FixedSpeedScroller extends Scroller {

        private int mDuration = 500;

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

        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator, boolean flywheel) {
            super(context, interpolator, flywheel);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        public void setScrollDuration(int duration) {
            mDuration = duration;
        }
    }
}

Problem

I have a `ViewPager` that I want to rotate automatically every 5 seconds, whilst also allowing the user to swipe too. However, when I set the automatic change, the transition animation between pages happens really quickly, and I want this to be slower. I've seen the answers for this question here: Slowing speed of Viewpager controller in android ...but they all use reflection. Does anyone know of any way of slowing down the automatic speed of a `ViewPager` without using reflection? I thought of using a `PageTransformer`, but not sure if that would work, and also it would probably affect the speed if the user swiped as well as the automatic one? Unless I can somehow detect the difference, and then do one or another `PageTransformation`?

Original source

Related problems