Is there any way to slow the scroll speed with the viewpager adaptor in android?
You know, I've been looking at this code. I can't figure out what I'm dong wrong.
try{ Field mScroller = mPager.getClass().getDeclaredField("mScroller"); mScroller.setAccessible(true); Scroller scroll = new Scroller(cxt); Field scrollDuration = scroll.getClass().getDeclaredField("mDuration"); scrollDuration.setAccessible(true); scrollDuration.set(scroll, 1000); mScroller.set(mPager, scroll); }catch (Exception e){ Toast.makeText(cxt, "something happened", Toast.LENGTH_LONG).show(); }
It doesn't change anything yet no exceptions occur?
I've started with HighFlyer's code which indeed changed the mScroller field (which is a great start) but didn't help extend the duration of the scroll because ViewPager explicitly passes the duration to the mScroller when requesting to scroll.
Extending ViewPager didn't work as the important method (smoothScrollTo) can't be overridden.
I ended up fixing this by extending Scroller with this code:
public class FixedSpeedScroller extends Scroller { private int mDuration = 5000; 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); } }
And using it like this:
try { Field mScroller; mScroller = ViewPager.class.getDeclaredField("mScroller"); mScroller.setAccessible(true); FixedSpeedScroller scroller = new FixedSpeedScroller(mPager.getContext(), sInterpolator); // scroller.setFixedDuration(5000); mScroller.set(mPager, scroller); } catch (NoSuchFieldException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { }
I've basically hardcoded the duration to 5 seconds and made my ViewPager use it.
Hope this helps.
I've wanted to do myself and have achieved a solution (using reflection, however). It's similar to the accepted solution but uses the same interpolator and only changes the duration based on a factor. You need to use a ViewPagerCustomDuration
in your XML instead of ViewPager
, and then you can do this:
ViewPagerCustomDuration vp = (ViewPagerCustomDuration) findViewById(R.id.myPager); vp.setScrollDurationFactor(2); // make the animation twice as slow
ViewPagerCustomDuration.java
:
import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.animation.Interpolator; import java.lang.reflect.Field; public class ViewPagerCustomDuration extends ViewPager { public ViewPagerCustomDuration(Context context) { super(context); postInitViewPager(); } public ViewPagerCustomDuration(Context context, AttributeSet attrs) { super(context, attrs); postInitViewPager(); } private ScrollerCustomDuration mScroller = null; /** * Override the Scroller instance with our own class so we can change the * duration */ private void postInitViewPager() { try { Class<?> viewpager = ViewPager.class; Field scroller = viewpager.getDeclaredField("mScroller"); scroller.setAccessible(true); Field interpolator = viewpager.getDeclaredField("sInterpolator"); interpolator.setAccessible(true); mScroller = new ScrollerCustomDuration(getContext(), (Interpolator) interpolator.get(null)); scroller.set(this, mScroller); } catch (Exception e) { } } /** * Set the factor by which the duration will change */ public void setScrollDurationFactor(double scrollFactor) { mScroller.setScrollDurationFactor(scrollFactor); } }
ScrollerCustomDuration.java
:
import android.annotation.SuppressLint; import android.content.Context; import android.view.animation.Interpolator; import android.widget.Scroller; public class ScrollerCustomDuration extends Scroller { private double mScrollFactor = 1; public ScrollerCustomDuration(Context context) { super(context); } public ScrollerCustomDuration(Context context, Interpolator interpolator) { super(context, interpolator); } @SuppressLint("NewApi") public ScrollerCustomDuration(Context context, Interpolator interpolator, boolean flywheel) { super(context, interpolator, flywheel); } /** * Set the factor by which the duration will change */ public void setScrollDurationFactor(double scrollFactor) { mScrollFactor = scrollFactor; } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, (int) (duration * mScrollFactor)); } }
Hope this helps someone!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With