2012-06-18 16 views
13

Tengo un problema con Fragments y cambio de orientación.Fragmentos que no funcionan correctamente después del cambio de orientación

Tengo una aplicación que tiene un MainActivity que maneja la conmutación Fragments a través de una barra de acciones con pestañas. Aquí está el código para la barra de acciones con pestañas y cuando se selecciona una pestaña.

private class MyTabListener <T extends android.support.v4.app.Fragment> implements ActionBar.TabListener { 
    private android.support.v4.app.Fragment mFragment; 
    private final Activity mActivity; 
    private final String mTag; 
    private final Class<T> mClass; 

    public MyTabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) { 
     mActivity = activity; 
     mTag = tag; 
     mClass = clz; 
    } 

    @Override 
    public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 
     if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
      mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
      ft.add(android.R.id.content,mFragment,mTag); 
     } else { 
      ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
     } 
    } 

    @Override 
    public void onTabUnselected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 
     if (mFragment != null){ 
      ft.detach(mFragment); // when a fragment is no longer needed, detach it from the activity but dont destroy it 
     } 
    } 

    @Override 
    public void onTabReselected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

    } 

La forma en que lo veo es que todo funciona bien cuando la aplicación se carga por primera vez en modo retrato. Cuando giro, por alguna razón, se agrega otra instancia de Fragment1 y luego no se desconecta cuando se selecciona otra pestaña. Este también es el caso cuando luego giro de nuevo a retrato.

He intentado usar setRetainInstance(true); en mi Fragments pero esto no funciona.

¿Hay algún método que deba anular o hacer algo con mi Fragments antes de girar?

Gracias de antemano.

EDIT He visto que onTabSelected se vuelve a llamar cuando se recrea la actividad. ¿Podría ser esta la causa de mi problema con los fragmentos adjuntos más de una vez?

Aquí están mis actividades en el método Crear.

super.onCreate(savedInstanceState); 

     if (savedInstanceState == null) { 
      //setContentView(R.layout.main); 

     } 
    // Create the Action Bar with tabs 
     ActionBar actionBar = getSupportActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
     actionBar.setDisplayShowTitleEnabled(false); 
     //create the tab for track and add it to the action bar. 
     Tab tab = actionBar.newTab() 
          .setText("Track") 
          .setTabListener(new MyTabListener<TrackingFragment>(this,"track",TrackingFragment.class)); 
     actionBar.addTab(tab); 

     //create the tab for ski tracks and add it to the action bar. 
     tab = actionBar.newTab() 
         .setText("Something Tracks") 
         .setTabListener(new MyTabListener<TrackListFragment>(this,"somethingtracks",TrackListFragment.class)); 
     actionBar.addTab(tab); 

     //create the tab for photos and add it to the action bar. 
     tab = actionBar.newTab() 
         .setText("Photos") 
         .setTabListener(new MyTabListener<PhotoFragment>(this,"photos",PhotoFragment.class)); 
     actionBar.addTab(tab); 

Respuesta

16

solución a corto:

En el método onTabSelected, antes de usar if (mFragment == null) que necesita para tratar de obtener el fragmento (usando mFragment = getSupportFragmentManager().findFragmentByTag(mTag)). También puedes configurar esto desde afuera, pero no te veo haciendo esto.

Comprobando if(savedInstanceState == null) en onCreate también podría resolver esto y considero que es un mejor enfoque! :)

+0

Si pongo mi código de barras de acción en el método onCreate, no se crea ni se muestra cuando la actividad se recrea después de un cambio de orientación. Voy a probar la parte supportManager ahora – StuStirling

+0

+1 ... entrando allí con la respuesta correcta mientras editaba. :) – Barak

+0

es el fragmento que no se transfiere cuando llama al setTabListener? – StuStirling

8

Parece que usted no tiene algo en su método de onCreate envuelto en una if(savedInstanceState == null), por lo que está creando otro fragmento, además de la que está siendo restaurado desde el haz savedInstanceState.

EDITAR

Mirando más de cerca a su código, creo que estaba equivocado sobre el onCreate, su onTabSelected debe manejarlo. Creo que tu if (mFragment == null) siempre es nulo, porque no tratas de encontrar el fragmento. Cambiar esa sección de código para:

@Override 
public void onTabSelected(Tab tab, android.support.v4.app.FragmentTransaction ft) { 

    mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag); // add this 

    if (mFragment == null){ // check to see if the fragment has already been initialised. If not create a new one. 
     mFragment = android.support.v4.app.Fragment.instantiate(mActivity, mClass.getName()); 
     ft.add(android.R.id.content,mFragment,mTag); 
    } else { 
     ft.attach(mFragment); // if the fragment has been initialised attach it to the current activity 
    } 
} 
+0

¿estamos hablando en mi fragmento o en mi actividad principal? – StuStirling

+0

Me atrevería a adivinar su actividad principal. Lo que te configura y muestra tu vista inicial. – Barak

+0

He agregado mi método onCreate a mi pregunta anterior – StuStirling

2

descubrí que es en realidad setRetainInstance ignorados y todos los fragmentos creados por el android.support.v4.app.FragmentManager se almacenan en onSaveInstanceState y se recrean en onCreate.

Para mí la solución era eliminar sin rodeos el fragmento superflua guardado: https://stackoverflow.com/a/13996054/341091

0

si (savedInstanceState == null) no está funcionando siempre. a veces savedInstanceState! = null, mientras que necesita agregar otro fragmento debido a la orientación horizontal.

Otro enfoque consiste en comprobar si fm.findFragmentById (R.id.frameLayoutLeft), independientemente de su orientación, es nulo o no, en caso afirmativo, entonces cree una nueva instancia de fragmento; de lo contrario, no haga nada. Si necesita un segundo fragmento en modo horizontal, primero debe comprobar si es horizontal o no, de ser así, compruebe si fm.findFragmentById (R.id.frameLayoutRight) es nulo o no. si es nulo, entonces crea, de lo contrario no hagas nada porque ya está guardado en el sistema operativo Android.

1

Tuve más o menos el mismo problema, pero las soluciones presentadas anteriormente no parecían funcionar en mi situación. Finalmente encontré la siguiente solución:

@Override 
public void onTabSelected(Tab tab, FragmentTransaction ft) { 
    if (mFragment == null) { 
     mFragment = Fragment.instantiate(mActivity, mClass.getName()); 
     ft.replace(android.R.id.content, mFragment, mTag); // Use replace iso add 
    } 
    else { 
     ft.attach(mFragment); 
    } 
} 
Cuestiones relacionadas