5

So che la tabulistica è stata trattata qui un milione di volte, da dieci milioni di persone. Ho i riferimenti degli sviluppatori e ho letto tutti i thread che riesco a trovare su SO. La mia domanda è, però, che i frammenti REALMENTE siano così complicati? Da quello che posso raccogliere, sembra che sia, mentre TabActivty è stato così facile. Vedere il seguente esempio:TabActivity -> Fragments .. è davvero così complicato?

mio codice corrente, necessaria per quattro schede, si presenta così:

Resources res = getResources(); // Resource object to get Drawables 
     TabHost tabHost = getTabHost(); // The activity TabHost 
     TabHost.TabSpec spec; // Resusable TabSpec for each tab 
     Intent intent; // Reusable Intent for each tab 

     // Create an Intent to launch an Activity for the tab (to be reused) 
     intent = new Intent().setClass(this, ServerActivity.class); 

     // Initialize a TabSpec for each tab and add it to the TabHost 
     spec = tabHost 
       .newTabSpec("server") 
       .setIndicator("Server", 
         res.getDrawable(R.drawable.ic_tab_server)) 
       .setContent(intent); 
     tabHost.addTab(spec); 

     // Do the same for the other tabs 
     intent = new Intent().setClass(this, StatusActivity.class); 
     spec = tabHost 
       .newTabSpec("status") 
       .setIndicator("Status", 
         res.getDrawable(R.drawable.ic_tab_status)) 
       .setContent(intent); 
     tabHost.addTab(spec); 

     intent = new Intent().setClass(this, LoggingActivity.class); 
     spec = tabHost 
       .newTabSpec("logging") 
       .setIndicator("Logs", 
         res.getDrawable(R.drawable.ic_tab_logging)) 
       .setContent(intent); 
     tabHost.addTab(spec); 

     intent = new Intent().setClass(this, DeliveryActivity.class); 
     spec = tabHost 
       .newTabSpec("deliveryqueue") 
       .setIndicator("Queue", res.getDrawable(R.drawable.ic_tab_queue)) 
       // .setIndicator("Delivery Queue", 
       // res.getDrawable(R.drawable.ic_tab_artists)) 
       .setContent(intent); 
     tabHost.addTab(spec); 

     tabHost.setCurrentTab(2); 
    } 

Secondo gli sviluppatori fanno riferimento, per l'equivelent di 4 schede, avete bisogno di tutto questo:

import java.util.HashMap; 

import com.example.android.supportv4.R; 

import android.content.Context; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentTransaction; 
import android.view.View; 
import android.widget.TabHost; 

/** 
* This demonstrates how you can implement switching between the tabs of a 
* TabHost through fragments. It uses a trick (see the code below) to allow 
* the tabs to switch between fragments instead of simple views. 
*/ 
public class FragmentTabs extends FragmentActivity { 
    TabHost mTabHost; 
    TabManager mTabManager; 

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

     setContentView(R.layout.fragment_tabs); 
     mTabHost = (TabHost)findViewById(android.R.id.tabhost); 
     mTabHost.setup(); 

     mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent); 

     mTabManager.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"), 
       FragmentStackSupport.CountingFragment.class, null); 
     mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"), 
       LoaderCursorSupport.CursorLoaderListFragment.class, null); 
     mTabManager.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"), 
       LoaderCustomSupport.AppListFragment.class, null); 
     mTabManager.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"), 
       LoaderThrottleSupport.ThrottledLoaderListFragment.class, null); 

     if (savedInstanceState != null) { 
      mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putString("tab", mTabHost.getCurrentTabTag()); 
    } 

    /** 
    * This is a helper class that implements a generic mechanism for 
    * associating fragments with the tabs in a tab host. It relies on a 
    * trick. Normally a tab host has a simple API for supplying a View or 
    * Intent that each tab will show. This is not sufficient for switching 
    * between fragments. So instead we make the content part of the tab host 
    * 0dp high (it is not shown) and the TabManager supplies its own dummy 
    * view to show as the tab content. It listens to changes in tabs, and takes 
    * care of switch to the correct fragment shown in a separate content area 
    * whenever the selected tab changes. 
    */ 
    public static class TabManager implements TabHost.OnTabChangeListener { 
     private final FragmentActivity mActivity; 
     private final TabHost mTabHost; 
     private final int mContainerId; 
     private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>(); 
     TabInfo mLastTab; 

     static final class TabInfo { 
      private final String tag; 
      private final Class<?> clss; 
      private final Bundle args; 
      private Fragment fragment; 

      TabInfo(String _tag, Class<?> _class, Bundle _args) { 
       tag = _tag; 
       clss = _class; 
       args = _args; 
      } 
     } 

     static class DummyTabFactory implements TabHost.TabContentFactory { 
      private final Context mContext; 

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

      @Override 
      public View createTabContent(String tag) { 
       View v = new View(mContext); 
       v.setMinimumWidth(0); 
       v.setMinimumHeight(0); 
       return v; 
      } 
     } 

     public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) { 
      mActivity = activity; 
      mTabHost = tabHost; 
      mContainerId = containerId; 
      mTabHost.setOnTabChangedListener(this); 
     } 

     public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) { 
      tabSpec.setContent(new DummyTabFactory(mActivity)); 
      String tag = tabSpec.getTag(); 

      TabInfo info = new TabInfo(tag, clss, args); 

      // Check to see if we already have a fragment for this tab, probably 
      // from a previously saved state. If so, deactivate it, because our 
      // initial state is that a tab isn't shown. 
      info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag); 
      if (info.fragment != null && !info.fragment.isDetached()) { 
       FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); 
       ft.detach(info.fragment); 
       ft.commit(); 
      } 

      mTabs.put(tag, info); 
      mTabHost.addTab(tabSpec); 
     } 

     @Override 
     public void onTabChanged(String tabId) { 
      TabInfo newTab = mTabs.get(tabId); 
      if (mLastTab != newTab) { 
       FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction(); 
       if (mLastTab != null) { 
        if (mLastTab.fragment != null) { 
         ft.detach(mLastTab.fragment); 
        } 
       } 
       if (newTab != null) { 
        if (newTab.fragment == null) { 
         newTab.fragment = Fragment.instantiate(mActivity, 
           newTab.clss.getName(), newTab.args); 
         ft.add(mContainerId, newTab.fragment, newTab.tag); 
        } else { 
         ft.attach(newTab.fragment); 
        } 
       } 

       mLastTab = newTab; 
       ft.commit(); 
       mActivity.getSupportFragmentManager().executePendingTransactions(); 
      } 
     } 
    } 
} 

È davvero così complesso? è come due - tre volte la quantità di codice per completare la stessa cosa. Voglio davvero evitare l'uso di metodi obsoleti, ma wow.

+1

Sì, sono deluso dal fatto che dobbiamo fare così tanto solo per creare schede. Per quanto posso dire, non c'è davvero nessun altro modo. Spero che qualcuno possa rispondere a questo. –

+0

Dai un'occhiata a questo: http://stackoverflow.com/questions/3163884/android-tabhost-withouttability/5098774#5098774 Questo potrebbe essere ciò che stiamo cercando entrambi (non posso dare un'occhiata in questo momento). È possibile utilizzare TabHost senza estendere TabActivity. –

risposta

1

La soluzione del documento dello sviluppatore è di circa 100 righe di codice aggiuntivo (più una sostituzione di visualizzazione). La soluzione fornita non è particolarmente complessa ed è estendibile in una posizione ovvia (onTabChanged) se si desidera attivare un'azione quando la scheda viene modificata. Non esiterei a usarlo perché otterrà i risultati che desideri. Mi stavo trasferendo da un ActionBar a TabHost e ho scoperto che si trattava di una sostituzione drop-in per la gestione dei miei frammenti esistenti.

+1

Grazie per questo. Mi dispiace per l'accettazione tardiva, sono stato davvero impegnato con il lavoro. Scoverò e capirò, java è ancora molto nuovo per me quindi alcune delle cose trattate nella guida per gli sviluppatori sono un po 'sopra la mia testa, ma sto imparando! –

+1

Ogni volta, spero che il tuo percorso nell'apprendimento sia facile. Non c'è molto da temere con Android, e anche Java è indulgente. Una parola di consiglio inutile, usando Log liberamente ti aiuterà molto nella ricerca di problemi. – blinkingwarninglight

Problemi correlati