2012-01-16 12 views
11

Ho un codice molto semplice in cui utilizzo la barra delle azioni con i frammenti di tabulazione. Funziona bene dopo il carico, ma dopo il cambio di orientamento diventa pazzesco. Anche il vecchio frammento è visibile (perché?).Scheda della barra delle azioni Android con vista a scorrimento con vista duplicata dopo il cambio di orientamento

Ci scusiamo per i testi ungheresi sull'immagine, ma spero che non importi. After orientation change

Allego il codice, forse aiuta a risolvere questo problema.

Principale attività:

public class Main extends Activity 
{ 
    private static ActionBar actionBar; 

    @Override 
    protected void onCreate(final Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     // setup action bar for tabs 
     actionBar = getActionBar(); 
     actionBar.removeAllTabs(); 
     if (actionBar.getTabCount() == 0) 
     { 
      actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 

      Tab tab = actionBar.newTab().setText(R.string.starter).setTabListener(new TabListener<Starter>(this, "starter", Starter.class)); 
      actionBar.addTab(tab); 

      tab = actionBar.newTab().setText(R.string.newword).setTabListener(new TabListener<NewWord>(this, "newwod", NewWord.class)); 
      actionBar.addTab(tab); 

      tab = actionBar.newTab().setText(R.string.feedback).setTabListener(new TabListener<Feedback>(this, "feedback", Feedback.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", getActionBar().getSelectedNavigationIndex()); 
    } 
} 

TabListener (lo stesso di Google esempio):

public class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener 
{ 
    private Fragment 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; 
    } 

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

    } 

    @Override 
    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 = Fragment.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); 
     } 

    } 

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

} 

Frammento:

public class Starter extends Fragment 
{ 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    { 
     setRetainInstance(false); 
     return inflater.inflate(R.layout.newword, container, false); 
    } 
} 

e l'XML di layout:

<?xml version="1.0" encoding="utf-8"?> 
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:padding="5dp" > 

    <LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" > 

     <TextView 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:padding="5dp" 
      android:text="@string/newword" 
      android:textAppearance="?android:attr/textAppearanceMedium" /> 

     <EditText 
      android:id="@+id/newwordtext" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/wordhint" /> 

     <TextView 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:padding="5dp" 
      android:text="@string/description" 
      android:textAppearance="?android:attr/textAppearanceMedium" 
      android:textStyle="bold" /> 

     <EditText 
      android:id="@+id/descriptionwordtext" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/descriptionhint" 
      android:inputType="textMultiLine" 
      android:minLines="4" /> 

     <TextView 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:padding="5dp" 
      android:text="@string/origin" 
      android:textAppearance="?android:attr/textAppearanceMedium" 
      android:textStyle="bold" /> 

     <EditText 
      android:id="@+id/origintext" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/originhint" /> 

     <TextView 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:padding="5dp" 
      android:text="@string/source" 
      android:textAppearance="?android:attr/textAppearanceMedium" 
      android:textStyle="bold" /> 

     <EditText 
      android:id="@+id/sourcetext" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:hint="@string/sourcehint" /> 

     <TextView 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:padding="5dp" 
      android:text="@string/name" 
      android:textAppearance="?android:attr/textAppearanceMedium" 
      android:textStyle="bold" /> 

     <EditText 
      android:id="@+id/nametext" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:inputType="textPersonName" /> 

     <Button 
      android:id="@+id/sendbutton" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_gravity="right" 
      android:text="@string/send" /> 
    </LinearLayout> 

</ScrollView> 

Grazie in anticipo!

risposta

5

ho trovato una risposta utilizzabile in altri question.

Ho bisogno di modificare il mio TabListener (mi sono trasferito nel mio principale classe di attività di classe interna):

private class TabListener<T extends Fragment> implements android.app.ActionBar.TabListener 
    { 
     private Fragment 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(final Activity activity, final String tag, final Class<T> clz) 
     { 
      mActivity = activity; 
      mTag = tag; 
      mClass = clz; 
     } 

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

     @Override 
     public void onTabSelected(final Tab tab, final FragmentTransaction ft) 
     { 
      mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag); 
      if (mFragment == null) 
      { 
       mFragment = Fragment.instantiate(mActivity, mClass.getName()); 
       ft.add(android.R.id.content, mFragment, mTag); 
      } 
      else 
      { 
       ft.attach(mFragment); 
      } 
     } 

     @Override 
     public void onTabUnselected(final Tab tab, final FragmentTransaction ft) 
     { 
      if (mFragment != null) 
      { 
       ft.detach(mFragment); 
      } 
     } 
    } 

Quindi, prima aggiungo frammento (di nuovo), lo controllo esistenza (e ottenere il suo riferimento) e se esiste lo allego solo

+1

L'unica cosa che vorrei aggiungere è che questa riga "mFragment = mActivity.getFragmentManager(). FindFragmentByTag (mTag);" Dovrebbe essere aggiunto anche nel metodo onTabUnselected prima di mFragment! = Null check. Altrimenti, ha funzionato alla grande! – SBerg413

+0

mFragment = mActivity.getFragmentManager(). FindFragmentByTag (mTag); risolto anche il mio problema, la classe non ha bisogno di essere interiore e privata. – Goldorak84

2

Provare a utilizzare ft.replace (R.id.content, mFragment) al posto di ft.attach (mFragment); nella funzione onTabSelected

+0

ho provato con questo...: ft.replace (android.R.id.content, mFragment); ma non aiuta (fa lo stesso problema) e dopo aver selezionato di nuovo la scheda è sposta il contenuto completo della scheda. – sianis

+0

Heh ...questo codice ha funzionato per me: 'if (fragmentManager.findFragmentById (R.id.frame_for_fragment) == null) { FragmentTransaction fragmentTransaction = fragmentManager .beginTransaction(); framment = new SomeFragment(); frammentTransaction.add (R.id.frame_for_fragment, frammento); fragmentTransaction.commit(); } ' – Orest

+0

Ma come posso inserire il codice nella mia applicazione? – sianis

0
public void onTabSelected(Tab tab, FragmentTransaction ft) 
    { 
     // Check if the fragment is already initialized 
     if (mFragment == null) 
     { 
      if(ft.findFragmentById(android.R.id.content) == null){ 
      // If not, instantiate and add it to the activity 
      mFragment = Fragment.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); 
     } 

    } 

Qualcosa del genere, perché il problema è che il vostro aggiungendo lo stesso frammento due volte, non ci resta che trovare dove ...

1

ho trovato una soluzione molto semplice per evitare frammenti duplicazioni:

public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { 
     Fragment currentFragment = getFragmentManager().findFragmentByTag(CURRENT_FRAGMENT_TAG); 
     if (currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass())) { 
      ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
      ft.add(android.R.id.content, mFragment, CURRENT_FRAGMENT_TAG); 
     } 
    } 

    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); 
     ft.remove(mFragment); 
    } 

La chiave della soluzione è nella condizione:

currentFragment == null || !currentFragment.getClass().equals(mFragment.getClass()) 

Questa condizione è valida solo se le classi dei frammenti sono diversi. Nel caso in cui tu abbia istanze diverse della stessa classe devi mettere un attributo extra nei tuoi frammenti per riconoscere la sua funzione (o l'associazione con e per rendere la condizione! CurrentFragment.getClass(). Equals (mFragment.getClass()) true : ad esempio, è possibile utilizzare la funzione di tag FragmentTransaction

Bye, Alex

0

ho risolto questo da solo guardando il frammento nel costruttore scheda ascoltatore

public class TabListener<T extends Fragment> implements ActionBar.TabListener 
{ 
    private Fragment fragment; 
    private final SherlockFragmentActivity activity; 
    private final String tag; 
    private final Class<T> clazz; 

    public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clazz) 
    { 
     this.activity = activity; 
     this.tag = tag; 
     this.clazz = clazz; 

     FragmentManager manager = ((SherlockFragmentActivity) activity).getSupportFragmentManager(); 
     fragment = manager.findFragmentByTag(tag); 
    } 
... 
} 
Problemi correlati