Android轮播循环ViewPager

Android开发常见的一个需求就是焦点图需要循环轮播,比如实际内容是5张焦点图,当在最后一张焦点图右滑时应该滑动至第一张焦点图,同样的,在第一张焦点图左滑应该滑动至最后一张焦点图。

原理与实现

网上有很多现成的包装好的类,只需要继承并且调用就行了,但是搞清楚它的原理很有必要。

一般焦点图是使用support v4提供的ViewPager来实现的,ViewPager的基本使用这里就不重复了,网上有很多。

这里我们使用一个基本的PagerAdapter来分析,改造成为轮播循环的ViewPager。

首先,使PagerAdapter#getCount()方法返回一个很大的数值,如

public int getCount() {
    return Integer.MAX_VALUE;
}

我们返回了Integer的最大值,虽然它还是一个有限的值,但是可以视作无限大。

假设我们的实际内容为List<MyData> realData,那我们在填充数据的时候需要使用下面的方法获取实际的数据位置

private int getRealPosition(int position) {
    return position % realData.size();
}

虽然焦点图每一张图的内容不一样,但它的结构是一样的,即布局一样。
这时,我们可以利用ListView的思想,将滑出屏幕的View缓存起来。当需要新View时,先去缓存中取,如果取不到,则自己创建;当View滑出屏幕时,我们首先将其从View Hierarchy中移除,然后将其加入缓存中。

这里我们可以利用ListView的父类AbsListView里的静态类RecyclerBin作为缓存管理器, 国外开源大神Jake Wharton已经帮我们移植好了,可以看开源项目 - salvage。

有了RecyclerBin的协助,我们在PagerAdapter的instantiateItem和destoryItem方法中可以这样操作

 public final Object instantiateItem(ViewGroup container, int position) {
    int viewType = getItemViewType(position);
    View view = null;
    if (viewType != IGNORE_ITEM_VIEW_TYPE) {
      view = recycleBin.getScrapView(position, viewType);
    }
    view = getView(position, view, container);
    container.addView(view);
    return view;
  }

  public final void destroyItem(ViewGroup container, int position, Object object) {
    View view = (View) object;
    container.removeView(view);
    int viewType = getItemViewType(position);
    if (viewType != IGNORE_ITEM_VIEW_TYPE) {
      recycleBin.addScrapView(view, position, viewType);
    }
  }

上面的getView方法其实就是参照ListAdapter的getView方法来创建的,使用方法一模一样。

至此,我们可以一直向右滑动了,但是初始状态却无法向左滑动,原因是初始状态时currentItem为0,这时,我们将currentItem设置为一个中间值即可,一般设为

Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % REAL_SIZE

其中REAL_SIZE就是真实的焦点图数量

现在,左右均可以任意循环轮播了。

如果需要自动滚动,则可以使用handler发送消息一直滚动ViewPager即可。

参考

  1. Android自动滚动 轮播循环的ViewPager
  2. JakeWharton/salvage

你可能感兴趣的:(android)