2012-09-07 28 views
10

Estoy usando un Viewpager con un FragmentPagerAdapter para permitir la adición y eliminación de páginas. Cada página muestra datos obtenidos de internet.Viewpager y FragmentPagerAdapter: eliminación de vista de página

Cuando se agrega una nueva página, se asocia un nuevo Fragmento a esa página. Los datos se obtienen a través de AsyncTask y se muestran en el Fragmento. Cuando el usuario elige eliminar una página, la idea es destruir la página y el Fragmento asociado.

En general, todo esto funciona bien. El problema que estoy viendo es la siguiente:

  1. tiene tres páginas con los datos:

    [Página 1] [Página 2] [Página 3]

  2. elimina cualquier página que no sea la última, diga la página 2; Page 2 desaparece como se desee:

    [Página 1] [Página 3]

  3. Se agrega una nueva página; pero en lugar de una nueva página en blanco, la nueva página muestra los datos (vista) desde la página 3.

    [Página 1] [Página 3] [Página 4, pero mostrando la vista/datos de la página 3, debe ser en blanco]


el código de eliminación de páginas en mi actividad es el siguiente:

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

Usando el depurador, se muestra que el fragmento se elimina de la FragmentManager después de la llamada executePendingTransactions(). Pero en la llamada FrampePagerAdapters, mAdapter.notifyDataSetChanged(), el fragmento se agrega de nuevo y luego se muestra cuando se crea una página nueva.

Intenté usar el FrameStatePagerAdapter, ya que eso debería permitir destruir fragmentos, pero no funcionó. En el método getItemPosition() de mi FragmentPagerAdapter, uso return FragmentAdapter.POSITION_NONE; como se señala en otro artículo SO que encontré.

Parece que la Vista de esa página no se destruye, sino que se vuelve a agregar a la nueva página. Intenté usar el método removeViewAt() en la vista de la página nueva, pero eso no funcionó.


ser nuevo en esto, estoy seguro de que me falta algo obvio ...

+0

no estoy seguro de que es algo obvio. Me estoy encontrando con este problema también. ¿Lo resolviste? Puede haber una respuesta aquí: http://stackoverflow.com/questions/12510404/reorder-pages-in-fragmentstatepageradapter-using-getitempositionobject-object –

+1

¿Puede mostrarnos su método invalidado? Public Fragment getItem (int position) – Gomino

+0

Cuándo está eliminando un fragmento, no lo elimina del adaptador. Es por eso que aparece de nuevo. Debe eliminarlo de su adaptador (no de la vista, sino del artículo, que utiliza en el método getItem()). el 4to fragmento se ve como el tercero porque reutiliza el fragmento, como el adaptador de ListView. Usted tiene un error en la lógica del adaptador. Muestra tu clase de adaptador –

Respuesta

1

Usted no debe extenderse FragmentStatePagerAdapter y quitar correspondiente elemento de la lista de elementos en ese adaptador, en lugar de tratar para eliminar un Fragmento de la actividad. No olvide llamar al adapter.notifyDataSetChanged() después de haber eliminado un artículo en el adaptador. Una vez hecho, ViewPager y FragmentStatePagerAdapter se encargarán del resto.

0

Ver su método getCount() devuelve el número exacto de elementos en viewPager. Y sí, FragmentStatePagerAdapter cuenta también.

0

he terminado con una solución que mezcla los siguientes conocimientos basados ​​en la experiencia:

  • Es posible añadir una nueva Fragment en la cola sin problemas.
  • No se puede leer un Fragment que se quitó previamente, ya que conduce a java.lang.IllegalStateException: Can't change tag of fragment a veces, así que tiene que clonarlo.
  • Para eliminar un Fragment debe devolver PagerAdapter.POSITION_NONE en el método getItemPosition(Object object), y eliminar el Fragment del FragmentManager.
  • Si está agregando/quitando/reemplazando en otro lugar diferente de la cola, tiene que quitar todo de la posición que está cambiando hasta el final, hacer las cosas, y luego leer el (clonado) Fragment s que quitó .

Aquí se trata de un código completo con un FragmentActivityFragmentPagerAdapter que tiene 3 métodos para añadir, quitar y reemplazar pestañas:

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

} 
Cuestiones relacionadas