2015-09-24 10 views
8

Ich entwickle eine App und derzeit versuche ich ScreenSlide dazu hinzuzufügen. Ich schaffte es, dies unter Verwendung einer tutorial zu tun, aber gewöhnliches Gleiten zwischen x Seiten ist nicht ganz das, was ich suche.Verschieben zwischen Fragmenten

Mit dem unten angegebenen Code kann ich zwischen 5 Seiten gleiten, aber die Seiten sind in einer geraden Linie ausgerichtet und Sie können nicht von der ersten Seite direkt in die 5. und umgekehrt gehen. In meiner App habe ich 4 Seiten. Wenn ich nach links rutsche, wechsle ich zwischen den ersten beiden Seiten, wenn ich nach rechts rutsche, wechsle ich zwischen zwei letzten Seiten. Auf dem Bild unten können Sie sehen, wie mein aktueller Code die Seite wechselt und darunter - mein Ziel.

enter image description here

public class MainActivity extends FragmentActivity { 
    private static final int NUM_PAGES = 5; 


    private ViewPager mPager; 
    private ScreenSlidePageFragment[] pages = new ScreenSlidePageFragment[NUM_PAGES]; 


    private PagerAdapter mPagerAdapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_screen_slide); 

     mPager = (ViewPager) findViewById(R.id.pager); 
     mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); 
     mPager.setAdapter(mPagerAdapter); 

    } 

    @Override 
    public void onBackPressed() { 
     if (mPager.getCurrentItem() == 0) { 
      super.onBackPressed(); 
     } else { 
      mPager.setCurrentItem(mPager.getCurrentItem() - 1); 
     } 
    } 

    private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { 
     public ScreenSlidePagerAdapter(FragmentManager fm) { 
      super(fm); 
     } 



     @Override 
     public int getCount() { 
      return NUM_PAGES; 
     } 

     @Override 
     public Fragment getItem(int position) { 
      boolean moveRight = mPager.getCurrentItem() < position; 
      boolean moveLeft = mPager.getCurrentItem() > position; 
      switch(position){ 
       case 5: 
        if(moveRight){ 

         return geLog.w("i" 
          + "Info", Integer.toString(position)); 
         //return getPageByPosition(2); 
        if(moveLeft) 
         return getPageByPosition(2); 


      } 
      return new ScreenSlidePageFragment(); 
     } 

     private Fragment getPageByPosition(int position){ 
      int index = position - 1; 
      if(index < 0 || index > NUM_PAGES-1) 
       throw new InvalidParameterException("requested position is invalid"); 

      if(pages[index] == null) 
       pages[index] = new ScreenSlidePageFragment(); 
      return pages[index]; 
     } 

    } 


} 

[UPDATE]

Ich habe es geschafft, einen Code zu schreiben, die mir zwischen 6 verschiedenen Seiten nach rechts unendlich gleiten kann. Die linke Seite ist jedoch begrenzt - ich kann nur auf die erste Seite gleiten (also wenn ich auf der ersten Seite bin, nachdem ich dreimal nach rechts gefahren bin, kann ich nur 3 Zyklen rückwärts machen). Ich denke, ich bin sehr nahe daran, die Lösung zu finden. Irgendwelche Ideen?

MainActivity.java

public class MainActivity extends FragmentActivity { 

private static final int NUM_PAGES = 6; 
private ViewPager pager; 
private PagerAdapter pagerAdapter; 
private List<ScreenSlidePageFragment> slideList; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    slideList = new ArrayList<ScreenSlidePageFragment>(); 
    for (int i = 0; i<NUM_PAGES; i++){ 
     ScreenSlidePageFragment slide = new ScreenSlidePageFragment(); 
     slide.setIndex(i+1); 
     slideList.add(slide); 
    } 

    pager = (ViewPager) findViewById(R.id.pager); 
    pagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); 
    pager.setAdapter(pagerAdapter); 
} 

private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { 

    public ScreenSlidePagerAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     int _pos = position % NUM_PAGES; 
     return slideList.get(_pos); 
    } 

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

ScreenSlidePageFragment.java

public class ScreenSlidePageFragment extends Fragment { 


     private int index; 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
      ViewGroup root = (ViewGroup)inflater.inflate(R.layout.slide, container, false); 
      TextView tw = (TextView) root.findViewById(R.id.textView); 
      tw.setText(Integer.toString(index)); 
      return root; 
     } 

     public void setIndex(int index){ 
      this.index = index; 
     } 
     } 
+4

schöne Zeichnung :) – Sunny

+0

Dies ist ein so verwirrender Fluss in Bezug auf Seite Dauerhaftigkeit und Benutzererfahrung, die ich Sie Ihr Navigations Design überdenken sehr empfehlen. Davon abgesehen müssen Sie wahrscheinlich die Animation und die Gestenerkennung selbst durchführen, anstatt den Pager-Adapter zu verwenden. Andernfalls müssen Sie den Pager-Adapter nach jedem Seitenwechsel ändern. http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html –

+0

Ich gab Ihnen +1 für die Zeichnung :-) – Christine

Antwort

3

Eine mögliche Abhilfe ist viewpager nicht verwenden, aber Ihre eigenen Slider zur Schaffung der ich mit dieser Lösung endete, da ViewPager sehr unflexibel, wie zum Beispiel, wenn Sie versuchen, etwas wie Facebook Page app Art der Sache zu tun. Nachteile: Sie müssen alle Berührungen und den Lebenszyklus verwalten.

Eine andere einfachere Lösung dafür ist grundsätzlich die folgende API zu verwenden, wenn ich die Frage richtig verstehe, sollte es genug sein. ViewPager.setCurrentItem

3

Dies ist, was ich tun würde.

Da Sie eine endliche Anzahl von Bildschirmen haben, würde ich ein Array erstellen, um jede Instanz der ScreenSlidePageFragment unter einem entsprechenden Index zu speichern. Sie können also eine Instanz von diesem Array abrufen, indem Sie "position" verwenden. Dies ermöglicht es Ihnen getItem Funktion zu nutzen, so etwas wie

... 
private ScreenSlidePageFragment[] pages = new ScreenSlidePageFragment[NUM_PAGES]; 
... 

@Override 
public Fragment getItem(int position) { 
    boolean moveRight = mPager.getCurrentItem() < position; 
    switch(position){ 
     case 1: 
      if(moveRight) 
       return getPageByPosition(3); 
      return getPageByPosition(2); 
     case 2: 
      if(moveRight) 
       //case when you are in a position 3 and swipe right - return first screen 
       return getPageByPosition(3); 
      //if you're swiping left from position 1, return the next screen 
      return getPageByPosition(1); 
     case 3: 
     //write out the rest of your logic 
     ... 
    } 
} 

private Fragment getPageByPosition(int position){ 
    int index = position - 1; 
    if(index < 0 || index > NUM_PAGES-1) 
     throw new InvalidParameterException("requested position is invalid") 

    if(pages[index] == null) 
     pages[index] = new ScreenSlidePageFragment(); 
    return pages[index]; 
} 

Hinweis zu tun: Code getestet nicht

Grundsätzlich müssen Sie die Logik schreiben, eine bestehende Instanz eines Fragments zurückzukehren, basierend auf dem Sie sind derzeit und welche Position ist gefragt.

+0

Ich habe Ihren Code implementiert, aber es hat nicht funktioniert. Ich habe den Prozess vereinfacht, so dass ich weniger Probleme habe und getestet werde, ob ich auf die erste Seite komme, wenn ich am 5. nach rechts wische - kein Erfolg. Ich habe den Code aktualisiert –

+1

haben Sie debuggen? Welches Fragment wird zurückgegeben, wenn 'position'' 5' ist? – C0D3LIC1OU5

+0

Ich frage mich auch, wie man sagen kann, was man ist, da man nichts in die Fragment-Instanz übergibt. Wenn es eine Benutzeroberfläche gibt, die anders aussehen kann, möchten Sie vielleicht auch Ihren Code überprüfen, um sicherzustellen, dass Sie Fragestatus richtig speichern/wiederherstellen, da Fragmente "onPause" und "onResume" ausführen sollen, wenn sie sich in der Ansicht – C0D3LIC1OU5

1

Ich denke, es ist möglich zu tun. 1. Setzen Sie die Objektanzahl von ViewPager auf Integer.MAX_VALUE und das aktuelle Element auf Integer.MAX_VALUE/2. Es gibt dir die Möglichkeit, eine falsche unendliche Schriftrolle zu erstellen. 2. Realisieren Sie Ihre Logik abhängig vom Fragment der aktuellen Position. Es ist einfach, wenn Sie sie in Ihrem Adapter speichern:

@Override 
    public Fragment getItem(int position) { 
     ItemFragmentRoot fragment = new ItemFragmentRoot(); 
     mFragmentMap.put(position, fragment); 
     return fragment; 
    } 

    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     super.destroyItem(container, position, object); 
     mFragmentMap.remove(position); 
    } 

    public ItemFragmentRoot getItem(int position){ 
     return mFragmentMap.get(position); 
    } 
  1. Und der schwierigste Teil, glaube ich.Da ViewPager mindestens eine Ansicht auf jeder Seite zwischenspeichert und Sie nicht wissen, auf welche Weise der Benutzer nur auf eine Art scrollen kann, wird das erscheinende Fragment gemäß der Scroll-Seite manuell initialisiert und neu initialisiert. Verwenden Sie ein geschachteltes Fragment in jedem ItemFragmentRoot, das ich bereits erwähnt habe. Alles hängt davon ab, wie stark Ihre Ansichtshierarchie ist.

Ich kann später mehr Code schreiben, wenn Sie brauchen.

2

können Sie versuchen, ViewPager.setCurrentItem

Wenn Sie

viewPager.setCurrentItem(PAGE_POS); 

zu Seite navigieren möchten Wenn Sie ohne glatte Scroll-Seite navigieren möchten

viewPager.setCurrentItem(PAGE_POS,false);