2015-09-24 24 views
8

Sto sviluppando un'applicazione e attualmente sto cercando di aggiungere ScreenSlide ad esso. Sono riuscito a farlo usando uno tutorial, ma il solito scorrimento tra le pagine x non è esattamente quello che sto cercando.Scorrere tra i frammenti

Con il codice fornito di seguito è possibile scorrere tra 5 pagine, ma le pagine sono allineate in linea retta e non è possibile passare dalla prima pagina direttamente alla 5a e viceversa. Nella mia app ho 4 pagine. Quando faccio scorrere a sinistra, passaggio tra le prime 2 pagine, quando faccio scorrere a destra passaggio tra le ultime 2 pagine. Nell'immagine sottostante puoi vedere come il mio codice corrente cambia pagina e sotto di esso - il mio obiettivo.

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]

Sono riuscito a scrivere un codice che mi permette di far scorrere infinitamente a destra tra le 6 pagine diverse. La parte sinistra è però limitata - posso scivolare solo alla prima pagina (quindi se sono sulla prima pagina dopo aver pedalato 3 volte a destra, posso fare solo 3 cicli all'indietro). Penso di essere molto vicino a trovare la soluzione. Qualche idea?

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

bel disegno :) – Sunny

+0

Questo è un flusso così confuso in termini di permanenza della pagina e di esperienza dell'utente che consiglio vivamente di riconsiderare la progettazione della navigazione. Detto questo, probabilmente dovrai eseguire l'animazione e il riconoscimento dei gesti da solo, invece di utilizzare l'adattatore per cercapersone. Altrimenti sarà necessario modificare l'adattatore del cercapersone dopo ogni cambio di pagina. http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html –

+0

Ti ho dato +1 per il disegno :-) – Christine

risposta

3

Una possibile soluzione non sta usando viewpager, ma creare il proprio personalizzato Slider, ho finito con questa soluzione, dal momento che ViewPager molto è non flessibile, come ad esempio se si tenta di fare qualcosa come app tipo di pagina Facebook. Contro: devi gestire tutti i tocchi e il ciclo di vita.

Un'altra soluzione più semplice per questo è fondamentalmente utilizzare la seguente API se ho capito bene la domanda dovrebbe essere sufficiente. ViewPager.setCurrentItem

3

Questo è quello che vorrei fare.

Poiché si dispone di una quantità limitata di schermate, vorrei creare una matrice per salvare ogni istanza dello ScreenSlidePageFragment effettuata con un indice corrispondente. Quindi puoi ottenere un'istanza da quell'array usando "position". Questo vi permetterà di sfruttare getItem funzione di fare qualcosa di simile

... 
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]; 
} 

Nota: il codice non testato

In sostanza, è necessario scrivere la logica di restituire un'istanza esistente di un frammento in base a dove si sono attualmente e quale posizione è richiesta.

+0

Ho implementato il codice, ma non ha funzionato. Ho semplificato il processo, in modo da ottenere meno problemi e testati, se riesco ad arrivare alla prima pagina se faccio scorrere verso destra il 5 ° - nessun successo. Ho aggiornato il codice –

+1

hai eseguito il debug? quale frammento viene restituito quando 'position' è' 5'? – C0D3LIC1OU5

+0

Mi chiedo anche come si possa sapere quale è quella in quanto non si passa nulla all'istanza del frammento. Se esiste un'interfaccia utente che può essere creata in modo diverso, è consigliabile controllare il codice per assicurarsi di salvare/ripristinare correttamente gli stati dei frammenti poiché i frammenti devono eseguire 'onPause' e' onResume' quando sono dentro e fuori dalla vista – C0D3LIC1OU5

1

Penso che sia possibile fare. 1. Impostare il numero di oggetti ViewPager su Integer.MAX_VALUE e l'elemento corrente su Intero.MAX_VALUE/2. Ti dà la possibilità di creare una scroll infinita finta. 2. Realizza la tua logica in base al frammento sulla posizione corrente. E 'facile se si memorizzano l'adattatore:

@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. E la parte più difficile, credo.Dal momento che ViewPager memorizza almeno 1 visualizzazione per lato e non sai in quale modo l'utente scorrerà l'unico modo è quello di inizializzare e reinizializzare manualmente il frammento visualizzato in base al lato di scorrimento. Usa il frammento annidato all'interno di ogni ItemFragmentRoot che ho menzionato prima. Tutto dipende da quanto pesante è la tua gerarchia di visualizzazione.

Posso scrivere più codice in un secondo momento, se necessario.

2

Si può provare ViewPager.setCurrentItem

Se si vuole navigare alla pagina

viewPager.setCurrentItem(PAGE_POS); 

Se si vuole navigare alla pagina senza scorrimento liscia

viewPager.setCurrentItem(PAGE_POS,false); 
1

seguire questo tutorial, questo è il meglio, l'ho usato nel mio ap.