如何制作ViewPager循环?

我有一个ViewPager有一些意见。 在最后一个正确的滑动之后我想去第一个。

我试过了

@Override public Fragment getItem(int arg0) { int i = arg0 % fragmentList.size(); return fragmentList.get(i); } @Override public int getCount() { return fragmentList.size()+1; } 

但是我得到了一个错误

 E/AndroidRuntime(22912): java.lang.IllegalStateException: Fragment already added: RubricFragment{4136cd80 #1 id=0x7f06000c android:switcher:2131099660:0} 

Solutions Collecting From Web of "如何制作ViewPager循环?"

一种可能性是设置这样的屏幕:

C'ABC A'

C'看起来就像C,但是当你滚动到那里时,它会将你切换到真实的C.一个'看起来就像A,但是当你滚动到那里时,它会切换到真实的A.

我会通过实现onPageScrollStateChanged这样做:

 @Override public void onPageScrollStateChanged (int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { int curr = viewPager.getCurrentItem(); int lastReal = viewPager.getAdapter().getCount() - 2; if (curr == 0) { viewPager.setCurrentItem(lastReal, false); } else if (curr > lastReal) { viewPager.setCurrentItem(1, false); } } } 

请注意,这将调用setCurrentItem的替代forms并传递false以使跳转立即发生,而不是作为平滑滚动。

我看到这个有两个主要的缺点。 首先,在到达任何一端时,用户必须让滚动结束才能继续前进。 其次,这意味着你的第一页和最后一页的所有视图的第二个副本。 根据你的屏幕资源如何,这可能会排除这种技术作为一种可能的解决scheme。

还要注意的是,由于视图分页器不会让点击通过底层控件,直到滚动完成之后,没有为A'和C'分片设置clicklisteners等等可能是好的。

编辑:现在自己实现这个,还有另一个主要的缺点。 从A'切换到A或C'切换到C时,屏幕至less会在当前的testing设备上闪烁片刻。

我会在ViewPager的末尾创build一个虚拟页面。 然后,当用户滚动到虚拟页面时,我使用此代码转到第一页。 我知道这是非常完美的:D

 @Override public void onPageScrolled(int position, float arg1, int arg2) { if (position >= NUM_PAGE-1) { mViewPager.setCurrentItem(0, true); } } 

我的解决scheme是基于benkc,但是第一页和最后一页滚动animation是禁用的,当页面“滚动”到实际页面时,滚动animation再次启用,该scheme可以解决第一个缺点。

但我ViewPager.setCurrentItem(position, false)结果仍然有滚动animation,所以我实现animation,太快看不到。

像这样的快速滚动animation,不介意评论,只是我的代码没有使用这些方法:

 public class FixedSpeedScroller extends Scroller { private int mDuration = 0; public FixedSpeedScroller(Context context) { super(context); } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { super.startScroll(startX, startY, dx, dy, mDuration); } @Override public void startScroll(int startX, int startY, int dx, int dy) { super.startScroll(startX, startY, dx, dy, mDuration); } } 

并使用此方法查看pager的活动

 private Scroller scroller; private void setViewPagerScroll(boolean instant) { try { Field mScroller = null; mScroller = ViewPager.class.getDeclaredField("mScroller"); mScroller.setAccessible(true); if (scroller == null) { scroller = (Scroller) mScroller.get(mViewPager); } FixedSpeedScroller fss = new FixedSpeedScroller(mViewPager.getContext()); mScroller.set(mViewPager, instant ? fss : scroller); } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } } 

并修改onPageScrollStateChanged像这样,只有第一页或最后一页(我有5页)会改变animation快速滚动,否则有正常的滚动:

 public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_IDLE) { if (position == 0) { setViewPagerScroll(true); mViewPager.setCurrentItem(3); } else if (position == 4) { setViewPagerScroll(true); mViewPager.setCurrentItem(1); } else { setViewPagerScroll(false); } } } 

FixedSpeedScroller引用在这里: http : //blog.csdn.net/ekeuy/article/details/12841409

这应该做没有虚拟页面的工作:

 private boolean isFirstOrLastPage; private int currentPageIndex = 0; @Override public void onPageScrolled(int arg0, float arg1, int arg2) { if(currentPageIndex!=arg0){ isFirstOrLastPage = false; return; } if((arg0==0 || arg0==PAGES.size()-1) && arg1 == 0 && arg2 == 0){ if(isFirstOrLastPage){ //DO SOMETHING }else{ isFirstOrLastPage = true; } } } @Override public void onPageSelected(int arg0) { currentPageIndex = arg0; } 

这个工作,接受的答案不好,因为发生循环时有一个滞后:

  @Override public int getCount() { return Integer.MAX_VALUE; } @Override public CharSequence getPageTitle(int position) { String title = mTitleList.get(position % mActualTitleListSize); return title; } @Override public Object instantiateItem(ViewGroup container, int position) { int virtualPosition = position % mActualTitleListSize; return super.instantiateItem(container, virtualPosition); } @Override public void destroyItem(ViewGroup container, int position, Object object) { int virtualPosition = position % mActualTitleListSize; super.destroyItem(container, virtualPosition, object); } 

回答采取从这里: ViewPager作为一个循环队列/包装