Tabs e swipe views

Nell’articolo Tab Layout in Android con ActionBar e Fragment spiego come implementare le tabs e nell’articolo Swipe views spiego come implementare le swipe views o scrolling tabs utilizzando ViewPager del Compatibility Package.
In questo articolo spiego come implementare 3 tabs dall’aspetto simile a quello dell’articolo Tab Layout in Android con ActionBar e Fragment ma con una funzionalità simile alle swipe views
In Implementing Effective Navigation è riportato un esempio per questo tipo di layout utilizzando ViewPager e FragmentPagerAdapter, che sono parte del Compatibility Package.
Ho notato che un codice simile si ottiene alla creazione di un nuovo progetto Android utilizzando Android SDK Tools Revision 20, e scegliendo come tipo di navigazione (Navigation Type) nel wizard di creazione del progetto “Tabs +Swipe” come in figura.

Il codice riportato in questo articolo è simile a quello in Implementing Effective Navigation ma con la modifica che i layout dei frammenti sono presi da file .xml

  1. crea un progetto Android
    • Build SDK: API 16
    • Minimum required SDK: API 14
    • non creare attività
  2. importa il Compatibility Package; potrebbe anche essere già stato importato se c’è una directory “libs” con il file android-support-v4.jar, altrimenti fai un click destro sul progetto e seleziona Android Tools -> Add Support Library o segui le istruzioni in Support Library
  3. modifica il file AndroidManifest.xml
  4. modifica il file res/values/strings.xml
  5. crea i file main.xml, tab1.xml, tab2.xml e tab3.xml nella cartella res/layout
    • main.xml
    • tab1.xml
    • tab2.xml
    • tab3.xml

      il file main.xml contiene un riferimento a ViewPager ma manca la parte relativa alla barra delle tab così come definita in Swipe views;
      i vari file tab*.xml contengono i layout dei frammenti
  6. crea il file eu/lucazanini/viewpager/MainActivity.java

    la classe principale estende FragmentActivity e non Activity come il solito;
    nell’evento onCreate tu colleghi una istanza di FragmentPagerAdapter (mCollectionPagerAdapter) a una istanza del ViewPager (mViewPager) derivata dal file main.xml ed è molto importante l’attivazione del NAVIGATION_MODE_TABS per la actionBar;
    nella classe interna CollectionPagerAdapter tu definisci il numero di tab (NUM_ITEMS) e sovrascrivi 3 metodi: getItem in cui crei i frammenti, getCount che semplicemente restituisce il numero di frammenti (tab) e getPageTitle che restituisce l’etichetta delle tab; in un’altra classe interna TabFragment sono creati frammenti scegliendo il layout sulla base del bundle passato al frammento nella classe CollectionPagerAdapter;
    la classe CollectionPagerAdapter non è static come in Implementing Effective Navigation per poter ottenere le risorse di tipo stringa nel metodo getPageTitle, altrimenti è necessario definire uno static Context nella classe principale
  7. lancia l’applicazione

47 risposte a “Tabs e swipe views”

  1. Great tutorial! I’m trying to do the exact same in a project I’m working on. I followed your tutorial and it worked perfectly on its own as the main activity but when I set it to open as a separate activity with an intent the app always crashes. Any ideas why that might be?

    1. I figured it out: I started making the app and only later tried to implement the tabs. The original was too low an API and didn’t have an ActionBar configured. That’s why the newer ones worked, I had started them with this layout in mind.

      Thanks again for the help

  2. ciao luca!
    Grazie per la guida.
    piccola domanda…se dovessi interagire con degli elementi delle varie tab? per esempio se volessi scrivere un messaggio su un textView come posso recuperare l’id ?
    con findViewById ottengo sempre null.
    COnsigli?

    grazie!

    1. findViewById restituisce l’oggetto con un determinato id in un file di layout; nel file xml, ad esempio, una TextView è dichiarata:

  3. Una spiegazione veramente molto ben fatta e lineare.

    Vorrei però porti un quesito:
    io ho messo nella prima tab uno Spinner (riempito dinamicamente con dati di un db) e una EditText per l’inserimento di stringhe per la ricerca all’interno dello Spinner.
    Il problema è che quando cambio e vado alla terza tab e poi torno alla prima non trovo i dati caricati nello spinner, mentre ad esempio rimangono le stringhe inserite nelle EditText.

    Puoi aiutarmi a risolvere questo problema?
    Grazie.

  4. Hi,
    great tutorial, helped me a lot to add tabs to my project, thanks a lot!!!

    But how can I use icons instead of text set @ tabLabel = getString(R.string.label1); for the tabs?

    Thanks in advance!

  5. Complimenti !!
    Grande Tutorial….ho però un problema….quando l’ applicazione la faccio partire sull’ emulatore è tutto O.K.
    Di contro ho problemi quando cerco di farla girare sul mio smartphone samsung s plus quando lancio l’ esecuzione non compare il il dispositivo per poterlo selezionare … è un problema che ho solo con questo progetto….
    Sarà forse legato all’ Api 14 ?

    Grazie mille !!

    1. Se il dispositivo non compare nell’elenco fra quelli disponibili significa che è escluso sulla base di quanto specificato nell’AndroidManifest.xml e probabilmente il samsung s plus ha le API 10.

  6. Bellissima guida è molto utile, però ho un problema, ho inserito un bottone nel file tab1.xml questo ha la funzione di aprire un altra activity, però quando vado a cliccare su di esso non funziona e non riesco a capire il perché.

  7. Nice…. i have wasted 3 days for implementing tab+swipe together……. finally i got a base idea from ur tutorial…. really thanks. :):):)

  8. Complimenti per il Tutorial, Una domanda:
    Ho provato ad inserire un precedente xml all’interno del tab1, nel mio xml era presente una ListView il cui layout era preso da un’altro xml (row.xml).
    Prima dell’implementazione dei tabs l’applicazione visualizzava correttamente la ListView, adesso mi da un’errore di compilazione nell’ attributo tools:listitem=”@layout/row” e l’errore e’: Attribute is missing the Android namespace prefix .
    hai una qualche idea per risolvere il problema?
    grazie

  9. I have the same question as a previous person (Hussain). Each tab will show a different layout with its own class which includes accessing a SQLite Database. It should be something like the this:

    int tabLayout = 0;
    switch (position) {
    case 0:
    //start new intent
    break;
    case 1:
    //start new intent
    break;
    case 2:
    //start new intent
    break;
    }

    I could not understand what meant in the reply. I´ve been searching day and night for help on this and I cannot find a suitable tutorial anywhere. I´ve followed two of your excellent tutorials, this and the swipe, but it just doesn´t help when each tab is meant to show a different class, with its own operations.

    Thanks
    Jon

  10. Hi, awesome tutorial! Easy to follow, I just have one question: I am using your sample for a project and I want to get rid of the tabs at the upper portion. I would just like to be able to slide through different activities without seeing the tabs.

    Thanks in advance!

  11. Hi, I have a little problem with webview fragment and ViewPager. To be more specific, with reloading webview after swipe tab. I know that you made a tutorial with onPause() method in which you describe how to avoid reloaidng, but I think that it doesn’t works with this tutorial.
    An in addition another question. I made a progressdialog whish is showing while loading pages. After I added viewpager it doesn’t disappear when page is loaded. How to fix it, or add progressbar in actionbar directly?

  12. Nice tutorial, but can any one helps me to start new Intent on each tab selected
    ex:

    int tabLayout = 0;
    switch (position) {
    case 0:
    //start new intent
    break;
    case 1:
    //start new intent
    break;
    case 2:
    //start new intent
    break;
    }

    1. In this example you must use Fragments or classes extending Fragments, but Intents launch activities, services or broadcast receivers.

    1. You might be missing

      int position = args.getInt(ARG_OBJECT);

      int tabLayout = 0;
      switch (position) {
      case 0:
      tabLayout = R.layout.tab1;
      break;
      case 1:
      tabLayout = R.layout.tab2;
      break;
      case 2:
      tabLayout = R.layout.tab3;
      break;
      }

      In the onCreateView method.

  13. While navigating from one tab to another I am getting a runtime exception which says ResourcesNotFoundException. Although all layouts have been registered.

  14. Thanks for this tutorial. I have a question. How can I set listener to editText in tab1. xml. I was trying to set it in mainActivity, but the null pointer error shows. I realised that app is searching for this editText in main.xml, not in tab1.xml. I think I should make tab1.class, and move all methods from mainActivity, to that new class. Can You give me some hints?

    1. You can replace the inner class TabFragment:

      Otherwise you can implement OnClickListener and override onClick

  15. Very nice tutorial. It works on my Sony Xperia Arc S with Android 4.0. Do you maybe know if it’s possible to use icons instead of strings in titles of each tab?

  16. Hey, Luca.

    Great tutorial. I was trying for sometime to do this and finally got it.
    But now i’ve got another problem, maybe you can help me.
    I’m trying to setText a TextView on a tab_.xml, but i keep getting NullPointerException.
    After some research, i found out that’s something about the tab_.xml not being the main view, so i cant access de TextView id;
    So… how can I access the tab_’s content?

    Thanks. o/

    1. In the inner static class TabFragment, in the onCreateView event you can set the text of a TextView:

      In the innser class CollectionPagerAdapter, in the getItem event you can set the text of a TextView:

  17. Very nice tut !! I’m looking for a tut like this one since a long time. Can you explain also how to load fragment instead of xml view ??

    Best regards

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.