2012-05-08 21 views
12

Estoy usando ActionBarSherlock para implementar un ActionBar con pestañas en mi aplicación. Cuando inicio la aplicación, y cambio de pestaña a pestaña, todo está bien. Sin embargo, cuando cambio del modo retrato al modo paisaje, el contenido de la última pestaña activa permanece visible. Cambiar a otra pestaña da como resultado el dibujo del nuevo contenido sobre el contenido anterior (ver imagen).El contenido de la pestaña permanece visible después de cambiar la pestaña después de cambiar la orientación

enter image description here

Mi clase principal:

public class TreinVerkeer extends SherlockFragmentActivity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setupTabs(savedInstanceState); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater inflater = getSupportMenuInflater(); 
     inflater.inflate(R.menu.menu, menu); 
     return true; 
    } 

    private void setupTabs(Bundle savedInstanceState) { 
     ActionBar actionBar = getSupportActionBar(); 
     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 

     Tab tab = actionBar.newTab().setText("STATIONS").setTabListener(new TabListener<StationsFragment>(this, "stations", StationsFragment.class)); 
     actionBar.addTab(tab); 

     tab = actionBar.newTab().setText("ROUTE").setTabListener(new TabListener<RouteFragment>(this, "route", RouteFragment.class)); 
     actionBar.addTab(tab); 

     tab = actionBar.newTab().setText("DELAYS").setTabListener(new TabListener<DelaysFragment>(this, "delays", DelaysFragment.class)); 
     actionBar.addTab(tab); 

     if (savedInstanceState != null) { 
      actionBar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0)); 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex()); 
    } 
} 

El TabListener (de "Adding Navigations Tabs" on the Android developer site con algunos cambios menores):

public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener { 
    private SherlockFragment mFragment; 
    private final Activity mActivity; 
    private final String mTag; 
    private final Class<T> mClass; 

    /** 
    * Constructor used each time a new tab is created. 
    * 
    * @param activity 
    *   The host Activity, used to instantiate the fragment 
    * @param tag 
    *   The identifier tag for the fragment 
    * @param clz 
    *   The fragment's Class, used to instantiate the fragment 
    */ 
    public TabListener(Activity activity, String tag, Class<T> clz) { 
     mActivity = activity; 
     mTag = tag; 
     mClass = clz; 
    } 

    /* The following are each of the ActionBar.TabListener callbacks */ 

    public void onTabSelected(Tab tab, FragmentTransaction ft) { 
     // Check if the fragment is already initialized 
     if (mFragment == null) { 
      // If not, instantiate and add it to the activity 
      mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName()); 
      ft.add(android.R.id.content, mFragment, mTag); 
     } else { 
      // If it exists, simply attach it in order to show it 
      ft.attach(mFragment); 
     } 
    } 

    public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
     if (mFragment != null) { 
      // Detach the fragment, because another one is being attached 
      ft.detach(mFragment); 
     } 
    } 

    public void onTabReselected(Tab tab, FragmentTransaction ft) { 
     // User selected the already selected tab. Usually do nothing. 
    } 
} 

Y StationsFragment (RouteFragment y DelaysFragment son los mismos, con la única texto diferente)

public class StationsFragment extends SherlockFragment { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.stationsfragment, container, false); 
    } 
} 

Con que el archivo de diseño de StationsFragment:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical" > 

    <TextView 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="Stations" /> 

</LinearLayout> 

Y, finalmente, el archivo de manifiesto:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.myapp" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="15" /> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:name=".TreinVerkeer" 
      android:label="@string/app_name" 
      android:theme="@style/Theme.Sherlock.Light" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

que tenían el mismo problema antes de inmediato al iniciar la aplicación (lo que sin ni siquiera cambiando la orientación), esto fue resuelto eliminando setContentView(R.layout.main) en el onCreate de la clase principal. Sin embargo, no puedo encontrar una solución para esto. Puede alguien ayudarme con esto?

+0

[ 'FragmentTabs.java'] (https://github.com/JakeWharton/ActionBarSherlock/blob/master/samples/fragments/src/com/actionbarsherlock/sample/fragments/FragmentTabs.java) –

Respuesta

19

FragmentManager restaurará automáticamente cualquier fragmento (y el historial) que se muestra actualmente en un cambio de configuración. Llame al findFragmentByTag para ver si ya existe una instancia del fragmento de destino antes de crear y adjuntar una nueva instancia.

15

Gracias a Jake, he actualizado el método onTabSelected así:

public void onTabSelected(Tab tab, FragmentTransaction ft) { 
    SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag); 

    // Check if the fragment is already initialized 
    if (mFragment == null && preInitializedFragment == null) { 
     // If not, instantiate and add it to the activity 
     mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName()); 
     ft.add(android.R.id.content, mFragment, mTag); 
    } else if (mFragment != null) { 
     // If it exists, simply attach it in order to show it 
     ft.attach(mFragment); 
    } else if (preInitializedFragment != null) { 
     ft.attach(preInitializedFragment); 
     mFragment = preInitializedFragment; 
    } 
} 

Esta respuesta es solamente para fines de aclaración, los créditos van a Jake :)

+3

Todavía , también te mereces accesorios para publicar este código. Es muy útil. Gracias :) – gnobal

5

Además de los cambios Niek publicó, hay un par de cambios triviales que debes hacer. Principalmente simplemente cambiando la actividad a SherlockFragmentActivity.

Para el beneficio de los demás, aquí está mi versión final que parece funcionar correctamente.

public static class TabListener<T extends SherlockFragment> implements ActionBar.TabListener 
    { 
     private SherlockFragment mFragment; 
     private final SherlockFragmentActivity mActivity; 
     private final String mTag; 
     private final Class<T> mClass; 

     /** Constructor used each time a new tab is created. 
     * @param activity The host Activity, used to instantiate the fragment 
     * @param tag The identifier tag for the fragment 
     * @param clz The fragment's Class, used to instantiate the fragment 
     */ 
     public TabListener(Activity activity, String tag, Class<T> clz) 
     { 
     mActivity = (SherlockFragmentActivity) activity; 
     mTag = tag; 
     mClass = clz; 
     } 


     public void onTabSelected(Tab tab, FragmentTransaction ft) 
     { 
     // Check if the fragment has already been initialised 
     SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag); 
     if (mFragment != null) 
     { 
      // If it exists, simply attach it in order to show it 
      ft.attach(mFragment); 
     } 
     else if (preInitializedFragment != null) 
     { 
      mFragment = preInitializedFragment; 
      ft.attach(mFragment); 
     } 
     else 
     { 
      // Not found, so instantiate and add it to the activity 
      mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName()); 
      ft.add(android.R.id.content, mFragment, mTag); 
     } 
     } 


     public void onTabUnselected(Tab tab, FragmentTransaction ft) 
     { 
     if (mFragment != null) { 
      // Detach the fragment, because another one is being attached 
      ft.detach(mFragment); 
     } 
     } 


     public void onTabReselected(Tab tab, FragmentTransaction ft) 
     { 
     // User selected the already selected tab. Usually do nothing. 
     } 
    } 
+0

Teniendo en cuenta el mismo caso que el anterior tengo un Sherlock Listfragment y un Sherlock Fragment. ¿Cómo se hace para que el oyente de pestañas sea genérico y admita tanto la lista como el fragmento normal? –

Cuestiones relacionadas