Reemplaza un Fragmento con otro en ViewPager

Estoy teniendo problemas cuando trato de reemplazar un Fragment por otro en un ViewPager .

Situación actual

Tengo un ViewPager con 3 páginas, cada una es un Fragment . En la primera página, tengo un ListView dentro de un ListFragment (“FacturasFragment”). Cuando hago clic en un elemento de esa lista, uso el método onListItemClick para manejar ese evento.

Lo que quiero

  • Cuando se hace clic en el elemento de la lista, quiero reemplazar ListFragment (contiene una lista de facturas) con otro Fragment (“DetallesFacturaFragment”, contiene detalles de la factura).
  • Cuando estoy en “DetallesFacturaFragmento” y ListFragment Button Atrás, debería volver a ListFragment .
  • El desplazamiento entre páginas no debería cambiar. Fragment visualizado en la primera. Es decir, si estoy en la primera página con “DetallesFacturaFragmento” y avanzo a la segunda página, cuando regrese al primero, debe continuar mostrando “DetallesFacturaFragmento”.

Código

FragmentActivity

 public class TabsFacturasActivity extends SherlockFragmentActivity { private MyAdapter mAdapter; private ViewPager mPager; private PageIndicator mIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_pager); mAdapter = new MyAdapter(getSupportFragmentManager()); mPager = (ViewPager)findViewById(R.id.pager); mPager.setAdapter(mAdapter); mIndicator = (TitlePageIndicator)findViewById(R.id.indicator); mIndicator.setViewPager(mPager); } private static class MyAdapter extends FragmentPagerAdapter { private String[] titles = { "VER FACTURAS", "VER CONSUMO", "INTRODUCIR LECTURA" }; private final FragmentManager mFragmentManager; private Fragment mFragmentAtPos0; private Context context; public MyAdapter(FragmentManager fragmentManager) { super(fragmentManager); mFragmentManager = fragmentManager; } @Override public CharSequence getPageTitle(int position) { return titles[position]; } @Override public Fragment getItem(int position) { switch (position) { case 0: // Fragment # 0 return new FacturasFragment(); case 1: // Fragment # 1 return new ConsumoFragment(); case 2:// Fragment # 2 return new LecturaFragment(); } return null; } @Override public int getCount() { return titles.length; } @Override public int getItemPosition(Object object) { if (object instanceof FacturasFragment && mFragmentAtPos0 instanceof DetallesFacturaFragment) return POSITION_NONE; return POSITION_UNCHANGED; } } } 

ListFragment

 public class FacturasFragment extends ListFragment { private ListView lista; private ArrayList facturas; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_facturas, container, false); facturas = myApplication.getFacturas(); lista = (ListView) view.findViewById(id.list); MyAdapter myAdaptador = new MyAdapter(this, facturas); setListAdapter(myAdaptador); return view; } public void onListItemClick (ListView l, View v, int position, long id) { myApplication.setFacturaActual(position); mostrarDatosFactura(); } private void mostrarDatosFactura() { final DetallesFacturaFragment fragment = new DetallesFacturaFragment(); FragmentTransaction transaction = null; transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.pager, fragment); //id of ViewPager transaction.addToBackStack(null); transaction.commit(); } private class MyAdapter extends BaseAdapter { private final FacturasFragment actividad; private final ArrayList facturas; public MyAdapter(FacturasFragment facturasActivity, ArrayList facturas) { super(); this.actividad = facturasActivity; this.facturas = facturas; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = actividad.getLayoutInflater(null); View view = inflater.inflate(R.layout.list_row, null, true); //Set data to view return view; } @Override public int getCount() { return facturas.size(); } @Override public Object getItem(int pos) { return facturas.get(pos); } @Override public long getItemId(int position) { return position; } private OnClickListener checkListener = new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }; } } 

Fragmento

 public class DetallesFacturaFragment extends SherlockFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_factura, container, false); //Set data to view return view; } } 

En este momento, cuando hago clic en un elemento de la lista, aparece una vista blanca en la primera página. He verificado y se onCreateView método onCreateView de “DetallesFacturaFragmento”, pero no aparece nada en esa página.

Y la primera vez que hago clic en el elemento de la lista, se muestra esa pantalla en blanco. Pero después de volver a la lista, tengo que hacer clic dos veces en un elemento de la lista para mostrar la pantalla en blanco.

He estado buscando en Google y mirando algunas preguntas, pero no he podido encontrar a nadie resuelto con el código completo.

Después de tantas horas gastadas, encontré el código de modificación correcto de la solución en esa respuesta .

Reemplaza a Fragment en la primera página de ViewPager por otro, y si regresas desde el segundo Fragment , el primer Fragment se muestra correctamente. No importa Fragment visualizado en la primera página, si desliza de una página a otra, no cambia su Fragment .

Aquí está mi código:

FragmentActivity

 public class TabsFacturasActivity extends SherlockFragmentActivity { public void onBackPressed() { if(mPager.getCurrentItem() == 0) { if (mAdapter.getItem(0) instanceof DetallesFacturaFragment) { ((DetallesFacturaFragment) mAdapter.getItem(0)).backPressed(); } else if (mAdapter.getItem(0) instanceof FacturasFragment) { finish(); } } } private static class MyAdapter extends FragmentPagerAdapter { private final class FirstPageListener implements FirstPageFragmentListener { public void onSwitchToNextFragment() { mFragmentManager.beginTransaction().remove(mFragmentAtPos0) .commit(); if (mFragmentAtPos0 instanceof FacturasFragment){ mFragmentAtPos0 = new DetallesFacturaFragment(listener); }else{ // Instance of NextFragment mFragmentAtPos0 = new FacturasFragment(listener); } notifyDataSetChanged(); } } private String[] titles = { "VER FACTURAS", "VER CONSUMO", "INTRODUCIR LECTURA" }; private final FragmentManager mFragmentManager; public Fragment mFragmentAtPos0; private Context context; FirstPageListener listener = new FirstPageListener(); public MyAdapter(FragmentManager fragmentManager) { super(fragmentManager); mFragmentManager = fragmentManager; } @Override public CharSequence getPageTitle(int position) { return titles[position]; } @Override public Fragment getItem(int position) { switch (position) { case 0: // Fragment # 0 if (mFragmentAtPos0 == null) { mFragmentAtPos0 = new FacturasFragment(listener); } return mFragmentAtPos0; case 1: // Fragment # 1 return new ConsumoFragment(); case 2:// Fragment # 2 return new LecturaFragment(); } return null; } @Override public int getCount() { return titles.length; } @Override public int getItemPosition(Object object) { if (object instanceof FacturasFragment && mFragmentAtPos0 instanceof DetallesFacturaFragment) { return POSITION_NONE; } if (object instanceof DetallesFacturaFragment && mFragmentAtPos0 instanceof FacturasFragment) { return POSITION_NONE; } return POSITION_UNCHANGED; } } } 

FirstPageFragmentListener

 public interface FirstPageFragmentListener { void onSwitchToNextFragment(); } 

FacturasFragment (FirstFragment)

 public class FacturasFragment extends ListFragment implements FirstPageFragmentListener { static FirstPageFragmentListener firstPageListener; public FacturasFragment() { } public FacturasFragment(FirstPageFragmentListener listener) { firstPageListener = listener; } public void onListItemClick (ListView l, View v, int position, long id) { firstPageListener.onSwitchToNextFragment(); } } 

DetallesFacturaFragmento (SecondFragment)

 public class DetallesFacturaFragment extends SherlockFragment { static FirstPageFragmentListener firstPageListener; public DetallesFacturaFragment() { } public DetallesFacturaFragment(FirstPageFragmentListener listener) { firstPageListener = listener; } public void backPressed() { firstPageListener.onSwitchToNextFragment(); } } 

Para resolver un problema menor, Android sugiere no usar el constructor no predeterminado para el fragmento. Deberías cambiar el constructor a algo como esto:

en FacturasFragmento:

  public static FacturasFragment createInstance(FirstPageFragmentListener listener) { FacturasFragment facturasFragment = new FacturasFragment(); facturasFragment.firstPageListener = listener; return facturasFragment; } 

Entonces puede llamarlo desde la función getItem de esta manera:

  mFragmentAtPos0 = FacturasFragment.createInstance(listener); 

en DetallesFacturaFragmento:

  public static DetallesFacturaFragment createInstance(FirstPageFragmentListener listener) { DetallesFacturaFragment detallesFacturaFragment= new DetallesFacturaFragment(); detallesFacturaFragment.firstPageListener = listener; return detallesFacturaFragment; } 

Luego puede llamarlo desde la función FirstPageListener.onSwitchToNextFragment () de esta manera:

  mFragmentAtPos0 = DetallesFacturaFragment.createInstance(listener);