Как создать цикл 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, но когда вы прокрутите туда, он переключит вас на реальный 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 и передает false чтобы заставить скачок происходить мгновенно, а не как гладкий свиток.

Я вижу два основных недостатка. Во-первых, по достижении любого конца пользователь должен пропустить прокрутку, прежде чем они смогут продолжить. Во-вторых, это означает наличие второй копии всех просмотров на вашей первой и последней странице. В зависимости от того, насколько ресурсоемкими являются ваши экраны, это может исключить эту технику в качестве возможного решения.

Заметим также, что, поскольку пейджер представления не позволяет кликам переходить к базовым элементам управления до тех пор, пока после прокрутки не будет достигнута договоренность, вероятно, прекрасно не настраивать кликнификаторы и т. П. Для фрагментов A и C.

Редактирование: теперь реализовав это сам, есть еще один довольно серьезный недостаток. Когда он переключается с A 'на A или C' на C, экран мерцает на мгновение, по крайней мере, на моем текущем тестовом устройстве.

Я бы создал фиктивную страницу в конце ViewPager. Затем я использую этот код, чтобы перейти на первую страницу, когда пользователь перейдет к фиктивной странице. Я знаю, что это далеко не идеальное: D

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

Мое решение основано на benkc, но анимация прокрутки первой и последней страницы отключена, а когда страницы «прокручиваются» до реальной страницы, прокрутка анимации снова включается, эта схема может решить первый недостаток.

Но мой результат ViewPager.setCurrentItem(position, false) по-прежнему имеет анимацию прокрутки, поэтому я реализую анимацию, которая слишком быстро просматривается.

Быстрая прокрутка анимации, как это, не против комментариев, только мой код не использовал этот метод:

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

И использовать этот метод для работы viewpager

 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 страниц) изменит анимацию на быструю прокрутку, в противном случае – обычная прокрутка:

 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 как круговая очередь / упаковка