2012-04-17 21 views
9

Ich habe einen ViewPager mit einigen Ansichten. Ich würde gerne zum ersten gehen, nachdem ich beim letzten gewischt habe.Wie erstellt man eine ViewPager-Schleife?

versuchte ich

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

@Override 
public int getCount() { 
    return fragmentList.size()+1; 
} 

Aber ich habe einen Fehler

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

Kontrolle dieses http://stackoverflow.com/q/7546224/1263908 – sique

+0

http://stackoverflow.com/questions/7440012/infinite-viewpager – blessenm

Antwort

5

ich eine Dummy-Seite am Ende des ViewPager schaffen würde. Dann verwende ich diesen Code, um zur ersten Seite zu gehen, wenn der Benutzer zur Dummy-Seite blättert. Ich weiß, es ist bei weitem nicht perfekt: D

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

wenn Sie dies tun Ja, du kannst unendlich scrollen, aber wenn du auf der letzten Seite scrollst, wirst du sehen, dass die Animation wie scren1 zurückgeht. –

24

Eine Möglichkeit, wie dies die Bildschirme der Einrichtung ist:

C

C‘‚ABCA‘sieht aus wie C, aber wenn man scrollen dort , schaltet man auf den realen C. A‘wie A aussieht, aber wenn Sie dort bewegen, schaltet man auf den realen A.

ich dieses onPageScrollStateChanged durch die Umsetzung tun würde etwa so:

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

Beachten Sie, dass dies die alternative Form der setCurrentItem aufruft und false der Sprung zu verursachen sofort und nicht als eine glatte Rolle passieren.

Es gibt zwei wesentliche Nachteile, die ich sehe. Erstens muss der Benutzer, wenn er das eine Ende erreicht, das Scrollen absetzen lassen, bevor es weiter gehen kann. Zweitens bedeutet das, dass Sie eine zweite Kopie aller Ansichten auf Ihrer ersten und letzten Seite haben. Je nachdem, wie ressourcenintensiv Ihre Bildschirme sind, kann diese Technik als mögliche Lösung ausgeschlossen werden.

Beachten Sie auch, dass der Klickpager die Klicks auf die darunter liegenden Steuerelemente erst nach dem Scrollen ablaufen lässt. Es ist wahrscheinlich in Ordnung, keine Clicklistener und ähnliches für die A- und C-Fragmente einzurichten.

Edit: Nachdem ich das jetzt selbst implementiert habe, gibt es noch einen weiteren großen Nachteil. Wenn es von A 'nach A oder C' nach C wechselt, flackert der Bildschirm zumindest für mein aktuelles Testgerät.

+0

Gute Antwort! Ich habe es benutzt und es funktioniert perfekt! – vandzi

+0

Hallo, konntest du einen Weg finden, das Flimmern zu vermeiden? – RMalke

+0

Erstaunliche Lösung für meine Aufgabe! Thx – mbelsky

0

dies sollte den Job ohne Dummy-Seiten tun:

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

dies funktioniert, die akzeptierte Antwort nicht gut, weil es eine Verzögerung ist, wenn die Schleife passiert:

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

Antwort von hier genommen: ViewPager as a circular queue/wrapping

1

Meine Lösung basiert auf benkc, aber die Scroll-Animation der ersten und letzten Seite ist deaktiviert, und wenn die Seiten auf die richtige Seite "gescrollt" werden, ist die Scroll-Animation wieder aktiviert. Dieses Schema kann den ersten Nachteil lösen.

aber mein ViewPager.setCurrentItem(position, false) Ergebnis ist immer noch Scroll-Animation, so dass ich Animationen, die zu schnell zu sehen ist implementiert.

die schnelle Scrollen Animation wie diese, kann den Kommentar nichts dagegen, nur mein Code diese Methode nicht verwenden: Aktivität

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

und verwendet diese Methode, um viewpager des

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

und modifizieren onPageScrollStateChanged so, nur die erste Seite oder die letzte Seite (ich habe 5 Seiten) würde die Animation in schnelles Scrollen ändern, ansonsten normales Scrollen:

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 Referenzen ist hier: http://blog.csdn.net/ekeuy/article/details/12841409

Verwandte Themen