2011-09-16 12 views
23

Io sto usando un ViewPager insieme ad un FragmentPagerAdapter per ospitare tre diversi frammentiSostituire frammento con un altro frammento all'interno ViewPager

[Fragment1][Fragment2][Fragment3] 

Quello che sto cercando di realizzare è quello di sostituire con successo Fragment1 con un intero nuovo frammento, Fragment4, se un compito specifico ha successo.

Quando uso ..

FragmentManager fragmentManager = getSupportFragmentManager(); 
FragmentTransaction transaction = fragmentManager.beginTransaction(); 
transaction.replace(R.id.fragment1_layout_id, fragment4); 
transaction.commit(); 

..il frammento viene sostituito in modo bello e Fragment4 è mostrato invece di Fragment1. Sebbene non riesca a scorrere fino a Fragment3 e poi a Fragment4, Fragment1 è tornato.

Poi di nuovo, se uso ..

FragmentManager fragmentManager = getSupportFragmentManager(); 
FragmentTransaction transaction = fragmentManager.beginTransaction(); 
transaction.remove(fragment1); 
transaction.commit(); 

..Fragment1 viene rimossa e quando torno Fragment4 c'è. Quindi il problema con questa soluzione è che non sono riuscito a trovare un modo per mostrare immediatamente Fragment4 come viene rimosso Fragment1, anche se ho provato:

transaction.add(fragment4); 
transaction.show(fragment4); 

Ed ecco come mia implementazione FragmentPagerAdapter sembra al momento, senza qualsiasi operazione di gestione:

public static class PagerAdapter extends FragmentPagerAdapter { 

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

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

    @Override 
    public Fragment getItem(int position) { 

     Fragment fragment = null; 

     switch (position) { 
     case 0: 
      fragment = Fragment1.newInstance(context_); 
      break; 

     case 1: 
      fragment = Fragment2.newInstance(context_); 
      break; 

     case 2: 
      fragment = Fragment3.newInstance(context_); 
      break; 

     default: 
      break; 
     } 

     return fragment; 
    } 
} 

Modifica.

Quindi sembra che non fosse completamente chiaro con la mia domanda. Ho deciso di rimuovere tutti gli spaghetti che sono riuscito a creare in precedenza e ho cercato di dichiarare che li avevo lasciati fuori (vedi testo in grassetto sopra).

Comunque qui è più o meno quello che ho cercato di fare all'interno getItem():

@Override 
public Fragment getItem(int position) { 

    Fragment fragment = null; 

    switch (position) { 
    case 0: 

     if (!app.isUserLoggedIn) { 
      if (loginFragment_ == null) { 
       loginFragment_ = LoginFragment.newInstance(context_); 
       transaction_ = fragmentManager_.beginTransaction(); 

       if (logoutFragment_ != null) { 
        transaction_.remove(logoutFragment_); 
        logoutFragment_ = null; 
       } 

       transaction_.add(loginFragment_, "login"); 
       transaction_.commit(); 
      } 

      if (fragmentManager_.findFragmentByTag("login") == null) 
       fragment = LoginFragment.newInstance(context_); 
      else 
       fragment = fragmentManager_.findFragmentByTag("login"); 

     } else { 
      if (logoutFragment_ == null) {      
       logoutFragment_ = LogoutFragment.newInstance(context_); 
       transaction_ = fragmentManager_.beginTransaction(); 

       if (loginFragment_ != null) { 
        transaction_.remove(loginFragment_); 
        loginFragment_ = null; 
       } 

       transaction_.add(logoutFragment_, "logout"); 
       transaction_.commit(); 
      } 

      if (fragmentManager_.findFragmentByTag("logout") == null) 
       fragment = LogoutFragment.newInstance(context_); 
      else 
       fragment = fragmentManager_.findFragmentByTag("logout"); 
     } 
     break; 

    case 1: 
     fragment = HomeFragment.newInstance(context_); 
     break; 

    case 2: 
     fragment = RegisterFragment.newInstance(context_); 
     break; 

    default: 
     break; 
    } 

    return fragment; 
} 

Con questo codice ottengo nulla di fatto, ma se qualcuno vede quello che sto facendo male e vorrei sottolineare io nella giusta direzione, lo apprezzerei molto!

+0

Penso che dovresti cambiare getItem in PagerAdapter. C'è un frammento restituito che deve essere visibile. – pawelzieba

+0

@dziobas È esattamente dove ho cercato di fare la magia che ho descritto nella mia domanda, senza fortuna. – velu

+0

fragment2 viene chiamato quando faccio clic su tab1, non so perché viene chiamato tab2? è un errore dell'adattatore? –

risposta

10

Prova utilizzando FragmentStatePagerAdapter

http://android-developers.blogspot.com/2011_08_01_archive.html

coz sarà rimuovere il frammento come si strisciare attraverso la vista (anche quando si chiama GetItem), quindi non è necessario rimuovere in modo esplicito da soli.

Ho avuto lo stesso problema per me.

Provo il codice e rimuovo il blocco if (fragment!=null) e funziona.

+0

Potete mostrare qualche codice plz. Ti sarei molto grato, perché ho seguito i tuoi passi e non ho capito che volevo ... – cesards

0

In alcune circostanze la tua istruzione getItem non restituisce fragment4 per case 0?

+0

Sì, dovrebbe e ho cercato di trovare il modo corretto per farlo tutto il giorno. Ho aggiornato la mia domanda e ho aggiunto come ho cercato di farlo finora. – velu

0

Ehi Ho risolto questo problema utilizzando un Elenco all'interno del mio FragmentPagerAdapter per gestire i vari frammenti e quindi il mio getItem è come ...

public void addScreen(String tag, Class<?> clss, Bundle args){ 
     if(clss!=null){ 
      TabInfo info = new TabInfo(tag, clss, args); 
      screens.add(info); 
     } 
    } 
@Override 
    public Fragment getItem(int position) { 
     TabInfo info = screens.get(position); 
     return Fragment.instantiate(context, info.clss.getName(), info.args); 
    } 

Ho poi a livello di codice rimuovere/aggiungere/modificare l'ordine delle voci di elenco (frammenti) quindi chiamare il gestore

mAdapter.notifyDataSetChanged() 
3

Come Maurycy ha detto, è necessario chiamare mAdapter.notifyDataSetChanged() ogni volta che vuoi dire al ViewPager che i frammenti sono stati sostituiti. Tuttavia, devi anche sostituire la funzione astratta getItemPosition() nell'adattatore e restituire POSITION_NONE quando viene chiamato con un vecchio, da nascondere, frammento come argomento. In caso contrario, ViewPager manterrà tutti i frammenti correnti.

Per ulteriori informazioni e codice di esempio, vedere this answer a related question.

0

Vedere il mio answer a una domanda simile su come inserire/sostituire le schede con un ViewPager e FragmentPagerAdapter.

0

Prova a impostareScreenPageLimit su 5 (o in base al tuo caso) per evitare di ricaricare il frammento in modo che quello che avevi sostituito rimanga invece di essere ricaricato quando scorri.

mViewPager.setOffscreenPageLimit(5); 
Problemi correlati