2012-09-07 13 views
10

Sto utilizzando uncon uno FragmentPagerAdapter per consentire l'aggiunta e la rimozione di pagine. Ogni pagina mostra i dati ottenuti da internet.Viewpager e FragmentPagerAdapter: rimozione vista pagina

Come una nuova pagina viene aggiunta, un nuovo frammento è associato a quella pagina. I dati sono ottenuti tramite AsyncTask e visualizzati nel frammento. Quando l'utente sceglie di rimuovere una pagina, l'idea è di distruggere la pagina e il frammento associato.

In generale, tutto funziona bene. Il problema che sto vedendo è la seguente:

  1. avete tre pagine con i dati:

    [Pagina 1] [Pagina 2] [Pagina 3]

  2. si elimina qualsiasi pagina diversa da quella precedente, ad esempio pagina 2; Page 2 scompare come desiderato:

    [Pagina 1] [Pagina 3]

  3. Si aggiunge una nuova pagina; ma invece di una nuova pagina vuota, la nuova pagina mostra i dati (vista) da pagina 3.

    [Pagina 1] [Pagina 3] [Pagina 4, ma che mostra vista/dati della Pagina 3, dovrebbe essere vuoto]


il codice di rimozione pagina nella mia attività è la seguente:

// Destroy fragment for this page 
    DataListFragment curFrag = getFragmentByName(currentPage); 
    FragmentManager fm = getSupportFragmentManager(); 
    fm.beginTransaction().remove(curFrag).commit(); 
    fm.executePendingTransactions(); 
    curFrag = null; 

    // Remove page and update adapter 
    mPageTitles.remove(position);   
    mAdapter.notifyDataSetChanged(); 

Utilizzando il debugger, mostra che il frammento viene rimosso dal FragmentManager dopo la chiamata executePendingTransactions(). Ma nella chiamata FrampePagerAdapters, mAdapter.notifyDataSetChanged(), il frammento viene aggiunto nuovamente e quindi visualizzato quando viene creata una nuova pagina.

Ho provato a utilizzare FrameStatePagerAdapter, poiché ciò dovrebbe consentire di distruggere i frammenti, ma non ha funzionato. Nel metodo getItemPosition() di FragmentPagerAdapter, utilizzo return FragmentAdapter.POSITION_NONE; come indicato in un altro articolo SO che ho trovato.

Sembra che la vista per quella pagina non sia stata distrutta, ma poi aggiunta nuovamente nella nuova pagina. Ho provato a utilizzare il metodo removeViewAt() nella vista della nuova pagina, ma non ha funzionato.


Essendo nuovo a questo, sono sicuro che mi manca qualcosa ovvio ...

+0

io non sono sicuro che si tratta di qualcosa di ovvio. Anche io sto correndo su questo problema. L'hai risolto? Potrebbe esserci una risposta qui: http://stackoverflow.com/questions/12510404/reorder-pages-in-fragmentstatepageradapter-using-getitempositionobject-object –

+1

Puoi mostrarci il tuo metodo override: public Fragment getItem (int position) – Gomino

+0

When stai rimuovendo un frammento, non lo rimuovi dall'adattatore. Ecco perché appare di nuovo. Devi rimuoverlo dall'adattatore (non dalla vista, ma da Item, che usi nel metodo getItem()). il quarto frammento sembra terzo perché riusa il frammento, come l'adattatore di ListView. Hai sbagliato nella logica dell'adattatore. Mostra la tua classe di adattatore –

risposta

1

Si dovrebbe piuttosto estendere FragmentStatePagerAdapter e rimuovere voce corrispondente dalla lista di elementi in tale scheda, invece di cercare rimuovere un frammento dall'attività. Non dimenticare di chiamare adapter.notifyDataSetChanged() dopo aver rimosso un elemento nell'adattatore. Una volta fatto, ViewPager e FragmentStatePagerAdapter si prenderanno cura di tutto il resto.

0

Vedere il metodo getCount() restituisce il numero esatto di elementi nel viewPager. E sì, anche FragmentStatePagerAdapter conta.

0

ho finito con una soluzione che mescola la seguente conoscenza basata sull'esperienza:

  • È possibile aggiungere un nuovo Fragment in coda senza problemi.
  • Non è possibile leggere un Fragment che è stato precedentemente rimosso, poiché a volte porta a java.lang.IllegalStateException: Can't change tag of fragment, quindi è necessario clonarlo.
  • Per la rimozione di Fragment è necessario restituire PagerAdapter.POSITION_NONE nel metodo getItemPosition(Object object) e rimuovere Fragment da FragmentManager.
  • Se si aggiunge/rimuove/sostituisce in un altro luogo diverso dalla coda, è necessario rimuovere tutto dalla posizione che si sta modificando fino alla fine, fare le cose e quindi leggere il (clonato) Fragment s che è stato rimosso .

Qui si tratta di un codice completo FragmentActivity con un FragmentPagerAdapter che ha 3 metodi per aggiungere, rimuovere e sostituire schede:

public class TabTestActivity extends FragmentActivity implements 
     ActionBar.TabListener { 
    private SectionsPagerAdapter mSectionsPagerAdapter; 
    private ViewPager mViewPager; 
    private static int tabCount = 0; 
    private static String labelString = null; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     labelString = getString(R.string.title_section); 
     setContentView(R.layout.activity_tab_test); 
     final ActionBar actionBar = getActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     mSectionsPagerAdapter = new SectionsPagerAdapter(
       getSupportFragmentManager()); 
     mViewPager = (ViewPager) findViewById(R.id.pager); 
     mViewPager.setAdapter(mSectionsPagerAdapter); 
     mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 
        @Override 
        public void onPageSelected(final int position) { 
         (new Handler()).postDelayed(new Runnable() { 

          @Override 
          public void run() { 
           actionBar.setSelectedNavigationItem(position); 
          } 

         }, 1); 
        } 
       }); 

     for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { 
      actionBar.addTab(actionBar.newTab() 
        .setText(mSectionsPagerAdapter.getPageTitle(i)) 
        .setTabListener(this)); 
     } 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.tab_test, menu); 
     return true; 
    } 

    public void addNewTab() { 
     int position = (mSectionsPagerAdapter.getCount() > 0 ? mViewPager.getCurrentItem() : 0); 
     mSectionsPagerAdapter.insertFragment(position); 
     mViewPager.setCurrentItem(position, true); 
    } 

    public void removeTab() { 
     if (mSectionsPagerAdapter.getCount() > 0) { 
      int position = mViewPager.getCurrentItem(); 
      mSectionsPagerAdapter.removeFragment(position); 
     } 
    } 

    public void replaceTab() { 
     if (mSectionsPagerAdapter.getCount() > 0) { 
      int position = mViewPager.getCurrentItem(); 
      mSectionsPagerAdapter.replaceFragment(position);    
      mViewPager.setCurrentItem(position, false); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
     case R.id.action_add_tab: 
      addNewTab(); 
      return true; 
     case R.id.action_remove_tab: 
      removeTab(); 
      return true; 
     case R.id.action_replace_tab: 
      replaceTab(); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    @Override 
    public void onTabSelected(ActionBar.Tab tab, 
      FragmentTransaction fragmentTransaction) { 
     mViewPager.setCurrentItem(tab.getPosition()); 
    } 

    @Override 
    public void onTabUnselected(ActionBar.Tab tab, 
      FragmentTransaction fragmentTransaction) { 
    } 

    @Override 
    public void onTabReselected(ActionBar.Tab tab, 
      FragmentTransaction fragmentTransaction) { 
    } 

    public class SectionsPagerAdapter extends FragmentPagerAdapter { 

     private List<Fragment> currentFragments; 
     private FragmentManager fragmentManager; 

     public SectionsPagerAdapter(FragmentManager fm) { 
      super(fm); 
      fragmentManager = fm; 
      currentFragments = new ArrayList<Fragment>(); 
     } 

     public void insertFragment(int position) { 
      // Remove fragments from position 
      List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size())); 
      int i = currentFragments.size() - 1; 
      int j = -1; 
      int k = i; 
      while (i >= position) { 
       currentFragments.remove(i); 
       i--; 
       j++; 
      } 
      notifyDataSetChanged(); 
      final ActionBar actionBar = getActionBar(); 
      while (k >= position) { 
       actionBar.removeTabAt(k); 
       k--; 
      } 
      android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction(); 
      while (j >= 0) { 
       Fragment fragmentToRemove = fragmentsToRemove.get(j); 
       transaction.detach(fragmentToRemove); 
       transaction.remove(fragmentToRemove); 
       j--; 
      } 
      transaction.commit(); 
      fragmentManager.executePendingTransactions(); 
      notifyDataSetChanged(); 
      // Add new fragment 
      Fragment fragment = new DummySectionFragment(); 
      currentFragments.add(position, fragment); 
      notifyDataSetChanged(); 
      actionBar.addTab(actionBar.newTab() 
        .setText(mSectionsPagerAdapter.getPageTitle(position)) 
        .setTabListener(TabTestActivity.this), position); 
      // Readd fragments 
      if (fragmentsToRemove.size() > 0) { 
       i = 1; 
       for (Fragment fragmentToRemove : fragmentsToRemove) { 
        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragmentToRemove)); 
        notifyDataSetChanged(); 
        actionBar.addTab(actionBar.newTab() 
          .setText(mSectionsPagerAdapter.getPageTitle(position + i)) 
          .setTabListener(TabTestActivity.this), position + i); 
        i++; 
       } 
      } 
     } 

     public void removeFragment(int position) { 
      // Remove fragments from position 
      List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size())); 
      int i = currentFragments.size() - 1; 
      int j = -1; 
      int k = i; 
      while (i >= position) { 
       currentFragments.remove(i); 
       i--; 
       j++; 
      } 
      notifyDataSetChanged(); 
      final ActionBar actionBar = getActionBar(); 
      while (k >= position) { 
       actionBar.removeTabAt(k); 
       k--; 
      } 
      android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction(); 
      while (j >= 0) { 
       Fragment fragmentToRemove = fragmentsToRemove.get(j); 
       transaction.detach(fragmentToRemove); 
       transaction.remove(fragmentToRemove); 
       j--; 
      } 
      transaction.commitAllowingStateLoss(); 
      fragmentManager.executePendingTransactions(); 
      notifyDataSetChanged(); 
      // Readd fragments (except one) 
      if (fragmentsToRemove.size() > 1) { 
       i = 0; 
       for (Fragment fragment : fragmentsToRemove.subList(1, fragmentsToRemove.size())) { 
        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragment)); 
        notifyDataSetChanged(); 
        actionBar.addTab(actionBar.newTab() 
          .setText(mSectionsPagerAdapter.getPageTitle(position + i)) 
          .setTabListener(TabTestActivity.this), position + i); 
        i++; 
       } 
      } 
     } 

     public void replaceFragment(int position) { 
      // Remove fragments from position 
      List<Fragment> fragmentsToRemove = new ArrayList<Fragment>(currentFragments.subList(position, currentFragments.size())); 
      int i = currentFragments.size() - 1; 
      int j = -1; 
      int k = i; 
      while (i >= position) { 
       currentFragments.remove(i); 
       i--; 
       j++; 
      } 
      notifyDataSetChanged(); 
      final ActionBar actionBar = getActionBar(); 
      while (k >= position) { 
       actionBar.removeTabAt(k); 
       k--; 
      } 
      android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction(); 
      while (j >= 0) { 
       Fragment fragmentToRemove = fragmentsToRemove.get(j); 
       transaction.detach(fragmentToRemove); 
       transaction.remove(fragmentToRemove); 
       j--; 
      } 
      transaction.commit(); 
      fragmentManager.executePendingTransactions(); 
      notifyDataSetChanged(); 
      // Add new fragment 
      Fragment fragment = new DummySectionFragment(); 
      currentFragments.add(position, fragment); 
      notifyDataSetChanged(); 
      actionBar.addTab(actionBar.newTab() 
        .setText(mSectionsPagerAdapter.getPageTitle(position)) 
        .setTabListener(TabTestActivity.this), position); 
      // Readd fragments (except one) 
      if (fragmentsToRemove.size() > 0) { 
       i = 1; 
       for (Fragment fragmentToRemove : fragmentsToRemove.subList(1, fragmentsToRemove.size())) { 
        currentFragments.add(DummySectionFragment.cloneExistingFragment((DummySectionFragment)fragmentToRemove)); 
        notifyDataSetChanged(); 
        actionBar.addTab(actionBar.newTab() 
          .setText(mSectionsPagerAdapter.getPageTitle(position + i)) 
          .setTabListener(TabTestActivity.this), position + i); 
        i++; 
       } 
      } 
     } 

     @Override 
     public Fragment getItem(int position) { 
      if (currentFragments == null) { 
       currentFragments = new ArrayList<Fragment>(); 
      } 
      while (currentFragments.size() <= position) { 
       currentFragments.add(null); 
      } 
      if (currentFragments.get(position) != null) { 
       return currentFragments.get(position); 
      } 
      Fragment fragment = new DummySectionFragment(); 
      currentFragments.set(position, fragment); 
      return fragment; 
     } 

     @Override 
     public int getCount() { 
      return currentFragments.size(); 
     } 

     @Override 
     public int getItemPosition(Object object) { 
      int position = currentFragments.indexOf(object); 
      if (position == -1) { 
       return PagerAdapter.POSITION_NONE; 
      } 
      return position; 
     } 

     @Override 
     public CharSequence getPageTitle(int position) { 
      return ((DummySectionFragment)getItem(position)).getTitle(); 
     } 
    } 

    public static class DummySectionFragment extends Fragment { 
     private int sectionNumber; 

     public DummySectionFragment() { 
      super(); 
      sectionNumber = ++tabCount; 
     } 

     public static DummySectionFragment cloneExistingFragment(DummySectionFragment fragment) { 
      DummySectionFragment cloned = new DummySectionFragment(); 
      // Hack for avoiding autoincrement 
      --tabCount; 
      cloned.sectionNumber = fragment.getSectionNumber(); 
      return cloned; 
     } 

     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 
      View rootView = inflater.inflate(R.layout.fragment_tab_test_dummy, 
        container, false); 
      TextView dummyTextView = (TextView) rootView 
        .findViewById(R.id.section_label); 
      dummyTextView.setText(String.format(labelString, sectionNumber)); 
      return rootView; 
     } 

     public int getSectionNumber() { 
      return sectionNumber; 
     } 

     public String getTitle() { 
      return String.format(labelString, sectionNumber); 
     } 
    } 

} 
Problemi correlati