Swipe views

In un precedente articolo ho implementato un layout con 2 tab utilizzando una action bar e i frammenti; lo svantaggio di questo layout è quello che per l’utente sarebbe molto naturale passare da una vista all’altra trascinandole orizzontalmente in modo simile a Google Play.
In Horizontal View Swiping with ViewPager è spiegato come ottenere questo tipo di layout utilizzando ViewPager, che è 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 “Swipe Views + Title Strip” come in figura.

Il codice riportato in questo articolo è lo stesso di quello in Horizontal View Swiping with ViewPager 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 directory res/layout
    • main.xml
    • tab1.xml
    • tab2.xml
    • tab3.xml

    il file main.xml è diviso in 2 parti: nella prima parte (android.support.v4.view.ViewPager) è definito il ViewPager che contiene i vari frammenti delle tab, nella seconda parte (android.support.v4.view.PagerTitleStrip) è definita la barra delle tab specificando la sua posizione, colore e margine interno (padding);
    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 FragmentStatePagerAdapter (mCollectionPagerAdapter) a una istanza del ViewPager (mViewPager) derivata dal file main.xml;
    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 Horizontal View Swiping with ViewPager per poter ottenere le risorse di tipo stringa nel metodo getPageTitle, altrimenti è necessario definire uno static Context nella classe principale
  7. lancia l’applicazione

25 risposte a “Swipe views”

  1. Ciao Luca seguito tutti i tuoi passaggi di questo tutorial, ma dopo aver lanciato l’applicazione sul mio telefono mi compare la notifica che l’applicazione si è fermata, in Android Studio non ci sono errori! da cosa può dipendere? La mia versione di Android è 4.4.2! Ho anche seguito la spiegazione sul sito di Android Studio l’applicazione viene eseguita ma non avendo i singoli tab nella cartella Layout non so come inserire i contenuti! Complimenti per i tuoi tutorial!

  2. Ancora ciao, Vorrei inserire un bottone con un onClickActionListener, ad esempio in tab1. Come potrei fare? Ho dichiarato il bottone nel manifest ma nel codice java non so proprio dove inserirlo. Se provo mi crasha !

    1. Intendi setOnClickListener?
      Eventualmente qui trovi un esempio che forse riesci ad adattare.
      Il pulsante non deve essere dichiarato in AndroidManifest.xml

  3. Ciao, grazie per il tutorial. Come mai, nonostante il minimo SDK richiesto sia il 14, ovvero IceCream Sandwich, ci sono applicazioni simili anche per Android Gingerbread? Se provassi questo tutorial sulla mia versione, cioè 2.3.3, funzionerebbe?
    Grazie ancora.

    1. Credo di si, ma devi commentare le righe con actionBar nella classe MainActivity perchè la ActionBar è stata aggiunta con Android 3.0 (API level 11)

      1. Grazie poi ho risolto. Utilizzando la libreria Sherlock si riesce a bypassare questo problema di compatibilità e, al posto di estendere FragmentActivity, si estende SherlockFragmentActivity che ha gli stessi metodi.

        1. Ciao, sono nuovo della programmazione Android, sono nella stessa situazione proposta da te in questo commento (compatibilità con la 2.3.3), volevo chiedere come avere la libreria Sherlock, se si deve scaricare esternamente al sdk e come caricarla.

          1. Ho risolto, ma in
            final ActionBar actionBar = getSupportActionBar();
            mi da l’errore “Type mismatch: cannot convert from com.actionbarsherlock.app.ActionBar to android.app.ActionBar”,
            come potrei risolvere??

  4. Ciao Luca!avrei un dubbio. La mia app deve simulare una sorta di portafoglio all’interno del quale sono presenti diverse carte di credito. Nella mia schermata principale ho le prime 3 carte dell’utente. Se esegue lo swipe a destra vorrei vedere le altre carte (ovviamente se disponibili), sempre a 3 per view. Il mio problema è relativo al fatto che l’app è stata inizialmente progettata per un massimo di 3 carte, di conseguenza con un layout container con all’interno altri 3 layout(ognuno relativo ad una carta). Volendo ottenere ciò che ti ho descritto nelle righe precedenti, sarebbe possibile utilizzare la tua soluzione usando/ripetendo lo stesso layout(e quindi gli stessi id) per ogni view? O devo crearmi un layout con id diversi per ogni pagina?
    Spero di essermi spiegato chiaramente. Se hai bisogno di altri dettagli chiedi pure. Ti ringrazio. Ciao!!!

      1. In realtà no. Mi spiego meglio: ho modo di conoscere sin da subito il numero di carte totali che ha l’utente. La mia idea è che se mi trovo sulla view 1, mostro le carte con i dati relativi alle prime 3, se sono sulla view 2 mostro le carte(stessi id, ma dati diversi) con i dati delle carte dalla 4 alla 6, e cosi’ via..

        1. Durante lo swipe si vedono contemporaneamente anche se parzialmente il layout corrente e quello successivo, se ci sono View con lo stesso id mi aspetto che mostrino lo stesso contenuto ma questo non è il comportamento voluto.
          Quindi si dovrebbero usare più layout con id differenti; in alternativa è possibile usare il metodo setId della classe View per modificare l’id in runtime ma l’ho visto usato sempre in un contesto in cui tutto il layout era creato in runtime.

  5. Ciao, ho seguito il procedimento ma non riesco a capire come far si che all’avvio dell’app venga mostrato un tab diverso dal primo. Come si fa?

    1. Nella classe MainActivity alla fine del metodo onCreate aggiungi la riga

      per selezionare la seconda tab all’avvio.

  6. Ciao Luca,
    ho eseguito il tuo tutorial e, funziona tutto alla perfezione, ora però mi trovo davanti ad un quesito.
    Devo popolare le view dei fragment tramite valori presi da un db in maniera tale d’avere una sorta di catalogo che scorra con l’effetto swipe.
    Come posso eseguire un’operazione del genere?

    Grazie mille!

    1. Con effetto swipe credo si intenda il passare da un layout all’altro orizzontalmente, ma forse tu intendi voler scorrere il catalogo in senso verticale, allora potresti fare una ricerca per ListFragment.

  7. Thanks for this wonderful tutorial.
    I would like to know the flow of this activity, like which method is called at what event. i tried putting debug points but could not configure the flow. please help me.

    Thanks in advance

  8. Nice! I use this setup for my new app. Now I want to implement some communication
    betwenn the fragments. How is it possible to calculate a value in lets say fragment one
    and communicate this to fragment two and use it for an ongoing calculation there?
    Do you have some examples or tutorials or a general setup?
    Bye Tom

    1. You can use a variable member of the main activity.
      Let me guess that the value you want to pass between the fragments is a String called myString with setter and getter methods.
      You can access to myString in the fragments with the code:

      • MainActivity.getMyString();
        MainActivity.setMyString(…);
        if myString and getter and setter methods are static
      • ((MainActivity)getActivity()).getMyString();
        ((MainActivity)getActivity()).setMyString(…);
        if myString and getter and setter methods aren’t static

      You can also use the setArguments and getArguments to pass a Bundle object; in the example of this post I use a bundle to pass the position of the tabs (an int value).

  9. You are Incredible!!!

    Thank you so much for taking the time to write this out!
    I have tried a total of 6 other similar tutorials but none actually explained clearly how to break down each tab into an xml file for easy editing.
    2 days searching until I came across this gem!
    Thanks again!

    Have a wonderful day! =)

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.