2013-10-28 15 views
5

Ho trovato un sacco di questi messaggi in StackOverflow. Come molte altre persone, ho lo stesso problema con i contenuti delle schede che si sovrappongono quando si cambiano le schede. Nessuno dei consigli che ho trovato non ha funzionato con il mio problema.Contenuti della scheda ActionBar sovrapposti

All'avvio dell'applicazione, viene visualizzato correttamente il contenuto della prima scheda. Quando faccio clic sull'altra scheda, i vecchi contenuti rimangono sullo schermo e anche il contenuto dell'altro tab viene aggiunto sullo schermo. Quando si cambiano le schede una seconda volta, tutti i contenuti scompaiono. Le schede di commutazione non funzioneranno più.

Ho seguito il documento dello sviluppatore di Google here.

La mia applicazione ha questo metodo onCreate .. La classe estende dalla libreria di supporto android.support.v7.app.

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

    ActionBar actionBar = getSupportActionBar(); 
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 
    actionBar.setDisplayShowTitleEnabled(false); 

    Tab tab = actionBar.newTab().setText("TAB1").setTabListener(new TabListener<Tab1Class>(this, "tab1", Tab1Class.class)); 
    actionBar.addTab(tab); 

    tab = actionBar.newTab().setText("TAB2").setTabListener(new TabListener<Tab2Class>(this, "tab2", Tab2Class.class)); 
    actionBar.addTab(tab); 
} 

La mia classe TabListener viene copiato dalla pagina ho linkato:

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

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

    @Override 
    public void onTabSelected(Tab tab, FragmentTransaction ft) { 
     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(Tab tab, FragmentTransaction ft) { 
     if(mFragment != null) { 
      ft.detach(mFragment); 
     } 
    } 

    @Override 
    public void onTabReselected(Tab tab, FragmentTransaction ft) {} 
} 

Entrambe le classi che uso come il contenuto delle schede estendono Frammento da android.support.v4.app.Fragment. Gonfiano i loro layout nei metodi onCreateView.

Cosa c'è che non va?

risposta

7

Cosa c'è che non va?

Dopo un rapido sguardo attraverso il codice per il ActionBarActivity, sembra che ci sia un bug per il ICS e soprattutto nell'ambito dell'attuazione del ActionBar (il codice dovrebbe funzionare per ICS dispositivi pre), che si occupa anche delle le schede.

Nella classe ActionBarImplICS che rappresenta l'implementazione per ICS dispositivi sembra che il FragmentTransaction passato alla onTabUnselected() callback è completamente inutile in quanto non si impegna ovunque dopo ritorna callback di chi ascolta (la transazione si impegna per gli altri due callback di il TabListener). Quindi un frammento impegnato non verrà mai rimosso dal layout in una selezione di schede e rimarrà il contenuto sovrapposto (a causa dello FrameLayout che contiene entrambi i frammenti).

ho scritto un'altra implementazione dell'interfaccia TabListener che fa tutto il suo lavoro da uno solo dei callback, che non è influenzato da quanto sopra bug (onTabSelected()):

public class TabListenerImpl implements ActionBar.TabListener { 

    private List<TabInfo> mTabs = new ArrayList<TabInfo>(); 
    private Context mContext; 

    public TabListenerImpl(Context context) { 
     mContext = context; 
    } 

    @Override 
    public void onTabReselected(Tab tab, FragmentTransaction ft) { 

    } 

    @Override 
    public void onTabSelected(Tab tab, FragmentTransaction ft) { 
     // iterate over all of the tabs, match the tag we have and see if 
     // we also have a fragment instance for it. If we don't, create one 
     // and add it to the container, if we have an instance simply attach 
     // it. Detach every other tag which doesn't match the tag. 
     for (TabInfo t : mTabs) { 
      if (tab.getTag() == t.tag) { 
       if (t.pageFragment == null) { 
        t.pageFragment = Fragment.instantiate(mContext, 
          t.clazz.getName()); 
        ft.add(android.R.id.content, t.pageFragment, t.tag); 
       } else { 
        ft.attach(t.pageFragment); 
       } 
      } else { 
       if (t.pageFragment != null && !t.pageFragment.isDetached()) { 
        ft.detach(t.pageFragment); 
       } 
      } 
     } 
    } 

    @Override 
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
     // faulty method 
    } 

    /** 
    * Call this method BEFORE you call the actionBar.addTab() method! 
    * 
    * @param tag 
    *   a String representing the tag that was set on the tab to 
    *   identify itself 
    * @param clazz 
    *   the class of the Fragment 
    */ 
    public void addTab(String tag, Class<? extends Fragment> clazz) { 
     TabInfo ti = new TabInfo(); 
     ti.clazz = clazz; 
     ti.tag = tag; 
     mTabs.add(ti); 
    } 

    // wrapper class 
    private class TabInfo { 
     Class<? extends Fragment> clazz; 
     Fragment pageFragment; 
     String tag; 
    } 

} 

cui si poteva allora utilizzare come:

TabListenerImpl listener = new TabListenerImpl(this); 
Tab tab = actionBar.newTab().setText("TAB1").setTag("TAB1").setTabListener(listener); 
listener.addTab("TAB1", Tab1Class.class); 
actionBar.addTab(tab); 

tab = actionBar.newTab().setText("TAB2").setTag("TAB2").setTabListener(listener); 
listener.addTab("TAB2", Tab2Class.class); 
actionBar.addTab(tab); 

io vi consiglio di impostare un contenitore come la vista dei contenuti (e anche per il contenuto scheda) e non utilizzare il contenitore android.R.id.content. Tieni presente che la mia implementazione non si occupa delle modifiche alla configurazione.

+0

Fantastico! Ho affrontato un sacco di problemi perché voglio che l'applicazione funzioni su dispositivi API 10. Spero che le persone abbandonino quei vecchi telefoni e ne acquisiscano di nuovi con Android 4. BTW, sai perché la mia applicazione non ha un titolo quando usi queste schede? O perché il mio menu collassa in questi punti anche io ho Android: showAsAction = "always"? – MikkoP

+0

@MikkoP * sai perché la mia applicazione non ha un titolo quando si usano queste schede?* - questo sta accadendo solo quando usi le schede? E puoi sempre usare il metodo 'actionBar.setTitle()'. * O perché il mio menu collassa in questi punti anche io ho Android: showAsAction = "always"? * - hai voci di menu nel menu di overflow (il popup che appare quando fai clic sull'immagine a 3 punti)? – Luksprog

+0

Succede solo quando uso queste schede. 'actionBar.setTitle()' non cambia nulla, nemmeno 'setTitle()' dall'attività. E sì, queste voci di menu vengono visualizzate nel menu di overflow. Ho postato di nuovo una nuova domanda, quindi se qualcuno risponde, c'è una possibilità migliore che altri possano trovarla e farsi aiutare. http://stackoverflow.com/questions/19660334/menu-collapsing-when-using-actionbar-tabs-for-navigation – MikkoP

Problemi correlati