继承ViewPager实现自动滚动的例子已经很多了,不过有时候我们不想使用继承,比如一个类已经继承了ViewPager,或者不想更改过去的代码.
这里提供一个使用外部类的方法实现ViewPager自动翻页功能.直接上代码:
package lx.af.utils.ViewUtils; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import java.util.concurrent.TimeUnit; /** * author: lx * date: 15-12-15 * * helper to make ViewPager auto scroll */ public class ViewPagerAutoFlipper implements ViewPager.OnPageChangeListener { private static final long DEFAULT_FLIP_INTERVAL = TimeUnit.SECONDS.toMillis(3); private ViewPager mViewPager; private boolean mAutoFlip = false; private long mFlipInterval = DEFAULT_FLIP_INTERVAL; private long mLastFlipTime; private int mScrollState = ViewPager.SCROLL_STATE_IDLE; private int mPosition; public static ViewPagerAutoFlipper newInstance(ViewPager pager) { return new ViewPagerAutoFlipper(pager); } public ViewPagerAutoFlipper(ViewPager pager) { mViewPager = pager; mViewPager.addOnPageChangeListener(this); mPosition = mViewPager.getCurrentItem(); } /** * @param interval auto flip interval, in millis */ public ViewPagerAutoFlipper setInterval(long interval) { if (interval > 0) { mFlipInterval = interval; } else { throw new IllegalArgumentException("interval should be positive"); } return this; } /** * @return true if ViewPager is auto flipping; false otherwise */ public boolean isAutoFlip() { return mAutoFlip; } /** * start ViewPager auto flip */ public void start() { if (mViewPager != null) { mAutoFlip = true; mViewPager.removeCallbacks(mFlipRunnable); mViewPager.postDelayed(mFlipRunnable, mFlipInterval); } } /** * stop ViewPager auto flip. * should always call this in Activity.onDestroy to release handler callbacks, * or mem leak may occur. */ public void stop() { mAutoFlip = false; if (mViewPager != null) { mViewPager.removeCallbacks(mFlipRunnable); } } /** * reset to init state. * should be called after {@link ViewPager#setAdapter(PagerAdapter)} */ public void reset() { if (mViewPager != null) { mViewPager.removeCallbacks(mFlipRunnable); mViewPager.removeOnPageChangeListener(this); mViewPager.addOnPageChangeListener(this); mPosition = mViewPager.getCurrentItem(); mLastFlipTime = 0; mScrollState = ViewPager.SCROLL_STATE_IDLE; mViewPager.postDelayed(mFlipRunnable, mFlipInterval); } } @Override public void onPageSelected(int position) { mPosition = position; mLastFlipTime = System.currentTimeMillis(); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageScrollStateChanged(int state) { mScrollState = state; } private boolean canAutoFlip() { if (mViewPager == null || mViewPager.getAdapter() == null) { return false; } long interval = System.currentTimeMillis() - mLastFlipTime; if (interval < mFlipInterval - 300) { // postDelayed() is not so accurate about delay time, // we minus 300 to avoid post too soon caused by the deviation mViewPager.removeCallbacks(mFlipRunnable); mViewPager.postDelayed(mFlipRunnable, mFlipInterval - interval); return false; } return mAutoFlip && mScrollState == ViewPager.SCROLL_STATE_IDLE; } private Runnable mFlipRunnable = new Runnable() { @Override public void run() { if (mViewPager == null) { // unlikely return; } if (mViewPager.getWindowToken() == null) { // window token no longer valid, exit loop mViewPager.removeCallbacks(mFlipRunnable); mViewPager.removeOnPageChangeListener(ViewPagerAutoFlipper.this); return; } if (canAutoFlip()) { int count = mViewPager.getAdapter().getCount(); int next = (mPosition + 1 == count) ? 0 : mPosition + 1; mViewPager.setCurrentItem(next); } if (mAutoFlip) { mViewPager.removeCallbacks(mFlipRunnable); mViewPager.postDelayed(mFlipRunnable, mFlipInterval); } } }; }
使用也很简单:
ViewPagerAutoFlipper.newInstance(mViewPager).setInterval(2000).start();或者
// setAdapter 后调用 flipper.start() mViewPager.setAdapter(mAdapter); ViewPagerAutoFlipper flipper = new ViewPagerAutoFlipper(mViewPager); flipper.setInterval(3000); flipper.start(); ... flipper.stop(); ... // 重新 setAdapter 后需要调用 reset() mViewPager.setAdapter(mAdapter); flipper.reset();
一开始是在Activity的onDestroy()方法中显式调用flipper.stop(),后来觉得这样做太不优雅了,改为判断window token是否可用.
目前自测是可以的,不知是否有其他问题.
代码收录在我的Android App框架中:
https://github.com/liuxu0703/AppFrame/blob/master/appframe/src/main/java/lx/af/utils/ViewUtils/ViewPagerAutoFlipper.java
水平有限,有问题请指正~.