以编程方式滑动时更改ViewPager动画持续时间

Ixx*_*Ixx 69 animation android android-viewpager

我正在改变幻灯片

viewPager.setCurrentItem(index++, true);
Run Code Online (Sandbox Code Playgroud)

但它变快了.有没有办法手动设置动画速度?

搜索过,发现有人问到同样的地方(除了StackOverflow,也许我有运气:)),没有答案.

喜欢:

https://groups.google.com/group/android-developers/browse_thread/thread/a13405c0b5833893?fwc=1

提前致谢.

Ole*_*ich 104

我想做自己并且已经实现了解决方案(但是使用反射).我还没有测试它,但它应该工作或需要最小的修改.在Galaxy Nexus JB 4.2.1上测试.您需要ViewPagerCustomDuration在XML中使用a 而不是ViewPager,然后您可以这样做:

ViewPagerCustomDuration vp = (ViewPagerCustomDuration) findViewById(R.id.myPager);
vp.setScrollDurationFactor(2); // make the animation twice as slow
Run Code Online (Sandbox Code Playgroud)

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 {
            Field scroller = ViewPager.class.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            Field interpolator = ViewPager.class.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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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));
    }

}
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人!

  • 您的解决方案是迄今为止我发现的最好的解决方案,但是当行“ scroller.set(this,mScroller);”时 执行后,出现错误“ IllegalArgumentException:字段的值无效”。我猜这是因为使用了ViewPager子类...任何修复? (2认同)

lob*_*zik 35

基于@ df778899的答案Android ValueAnimator API,我找到了更好的解决方案.没有反射它工作正常,非常灵活.此外,无需自定义ViewPager并将其放入android.support.v4.view包中.这是一个例子:

private void animatePagerTransition(final boolean forward) {

    ValueAnimator animator = ValueAnimator.ofInt(0, viewPager.getWidth());
    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            viewPager.endFakeDrag();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            viewPager.endFakeDrag();
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    });

    animator.setInterpolator(new AccelerateInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        private int oldDragPosition = 0;

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int dragPosition = (Integer) animation.getAnimatedValue();
            int dragOffset = dragPosition - oldDragPosition;
            oldDragPosition = dragPosition;
            viewPager.fakeDragBy(dragOffset * (forward ? -1 : 1));
        }
    });

    animator.setDuration(AppConstants.PAGER_TRANSITION_DURATION_MS);
    if (viewPager.beginFakeDrag()) {
        animator.start();
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

只是检查是否可以使用此解决方案一次刷几页(例如,如果第一页应显示在最后一页之后).这是稍加修改的代码,用于处理指定的页数:

private int oldDragPosition = 0;

private void animatePagerTransition(final boolean forward, int pageCount) {
    // if previous animation have not finished we can get exception
    if (pagerAnimation != null) {
        pagerAnimation.cancel();
    }
    pagerAnimation = getPagerTransitionAnimation(forward, pageCount);
    if (viewPager.beginFakeDrag()) {    // checking that started drag correctly
        pagerAnimation.start();
    }
}

private Animator getPagerTransitionAnimation(final boolean forward, int pageCount) {
    ValueAnimator animator = ValueAnimator.ofInt(0, viewPager.getWidth() - 1);
    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            viewPager.endFakeDrag();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            viewPager.endFakeDrag();
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
            viewPager.endFakeDrag();
            oldDragPosition = 0;
            viewPager.beginFakeDrag();
        }
    });

    animator.setInterpolator(new AccelerateInterpolator());
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int dragPosition = (Integer) animation.getAnimatedValue();
            int dragOffset = dragPosition - oldDragPosition;
            oldDragPosition = dragPosition;
            viewPager.fakeDragBy(dragOffset * (forward ? -1 : 1));
        }
    });

    animator.setDuration(AppConstants.PAGER_TRANSITION_DURATION_MS / pageCount); // remove divider if you want to make each transition have the same speed as single page transition
    animator.setRepeatCount(pageCount);

    return animator;
}
Run Code Online (Sandbox Code Playgroud)


Cíc*_*ura 11

 public class PresentationViewPager extends ViewPager {

    public static final int DEFAULT_SCROLL_DURATION = 250;
    public static final int PRESENTATION_MODE_SCROLL_DURATION = 1000;

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

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

    public void setDurationScroll(int millis) {
        try {
            Class<?> viewpager = ViewPager.class;
            Field scroller = viewpager.getDeclaredField("mScroller");
            scroller.setAccessible(true);
            scroller.set(this, new OwnScroller(getContext(), millis));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class OwnScroller extends Scroller {

        private int durationScrollMillis = 1;

        public OwnScroller(Context context, int durationScroll) {
            super(context, new DecelerateInterpolator());
            this.durationScrollMillis = durationScroll;
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy, int duration) {
            super.startScroll(startX, startY, dx, dy, durationScrollMillis);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*rke 6

更好的解决方案是通过在支持包中创建类来简单地访问私有字段.编辑这是MAX_SETTLE_DURATIONViewPager班级设定的600毫秒.

package android.support.v4.view;

import android.content.Context;
import android.util.AttributeSet;

public class SlowViewPager extends ViewPager {

    // The speed of the scroll used by setCurrentItem()
    private static final int VELOCITY = 200;

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

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

    @Override
    void setCurrentItemInternal(int item, boolean smoothScroll, boolean always) {
        setCurrentItemInternal(item, smoothScroll, always, VELOCITY);
    }

}
Run Code Online (Sandbox Code Playgroud)

当然,您可以添加自定义属性,以便可以通过XML进行设置.

  • 是不是setCurrentItemInternal一个私有方法? (8认同)
  • @MartyMiller是的,但是如果支持lib是项目的一部分,你可以在它的包中创建一个类. (2认同)