Autore Topic: [medio] ViewPager con tabs interattivi  (Letto 10289 volte)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
[medio] ViewPager con tabs interattivi
« il: 21 Luglio 2012, 01:02:02 CEST »
+6
Livello di difficoltà : medio
Min SDK : 4
Sorgente : ZIP allegato


fonti:

Introduzione

Dopo aver visto il bellissimo tutorial di bradipao citato nelle fonti, e dopo aver usato e preso mano al suo codice (non me ne voglia), mi sono chiesto come fare ad avere quell'effetto swiping tabs che troviamo anche nel market (Mie Applicazioni) e in molti altri posti.

Il support package (compatibility library) già visto nel tutorial di bradipao, oltre a viewPager e Fragments, mette a disposizione un paio di interessantissime classi per fare ciò che ci interessa:
PagerTabStrip | Android Developers[/url]
http://developer.android.com/reference/android/support/v4/view/PagerTitleStrip.html

Le due classi si assomigliano come nome, ed in effetti, creano un effetto molto simile...
La prima crea una "TabStrip", cioè una striscia di tab interattiva, dove è possibile disegnare un selector (tab attivo), fare lo swipe tra i vari tab, e cliccare sul tab desiderato. Ad ogni azione, corrisponderà un'azione sui relativi fragment collegati.
La seconda classe, crea una semplice lista di "titoli" dei fragment. La lista scorrerà quando voi cambiate fragment, ma non risponderà ad alcun input utente. Un po meno utile, ma stilisticamente carina.

Contenuto del tutorial e layout

Questo tutorial sarà molto breve, ogni cosa non spiegata qui, si può trovare nel tutorial corposo ed esaustivo di bradipao, diamo a cesare quel che è di cesare, se vi interessa conoscere di più sui fragment, lui ve li spiega molto bene!
Ma ora passiamo a quello che più interessa, il codice!

Per prima cosa, va modificato il layout dell'activity che contiene il view pager.
E' sufficiente dichiarare come figlio dell'oggetto ViewPager un oggetto che può essere PagerTabStrip oppure PagerTitleStrip, il quale avrà diversi parametri.

Codice (XML): [Seleziona]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="[url]http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:gravity="center_horizontal"
   android:orientation="vertical" >
    <android.support.v4.view.ViewPager
       android:id="@+id/pager"
       android:layout_width="fill_parent"
       android:layout_height="0dp"
       android:layout_weight="1" >
        <!-- DECOMMENT IF YOU WANT INTERACTIVETABS <android.support.v4.view.PagerTabStrip -->
        <!-- DECOMMENT IF YOU WANT NON INTERACTIVETABS <android.support.v4.view.PagerTitleStrip -->
        <android.support.v4.view.PagerTabStrip
           android:id="@+id/pagerTabStrip"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="top"
           android:background="#33B5E5"
           android:paddingBottom="2dp"
           android:paddingTop="1dp"
           android:textColor="#FFFFFF" />
    </android.support.v4.view.ViewPager>
</LinearLayout>

Tralasciando quelli classici, abbiamo layout_gravity che ci aiuta a posizionare la striscia, background che rappresenta lo sfondo della striscia, la parte blu negli screenshot sotto.
Il padding top e bottom che rappresenta la spaziatura interna per il testo (più è grande piu alta sarà la striscia)ed il colore del testo (bianco nell'esempio).
Altri parametri possono essere settati a runtime da codice, come vedremo.

Aggiunta e configurazione della Strip

Nella OnCreate dell'activity creiamo i fragment (in una lista) ed una lista di titoli per i fragment (Nell'esempio ho usato il className come titolo, si può usare qualsiasi stringa).
Dopo aver poi inizializzato il viewPager, andiamo a fare una findView per ottenere il pagerStrip; nell'esempio ho verificato a runtime il tipo di pagerStrip usato, questo non è necessario sempre, lo è stato solo qui, per poter fare un unico tutorial con entrambi i pagerStrip.

Codice (Java): [Seleziona]
  // list contains fragments to instantiate in the viewpager
  List<Fragment> fragments = new Vector<Fragment>();
  List<String> fragmentTitles = new Vector<String>();
  // page adapter between fragment list and view pager
  private PagerAdapter mPagerAdapter;
  // view pager
  private ViewPager mViewPager;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // creating fragments and adding to list
        fragments.add(Fragment.instantiate(this, Page1Fragment.class.getName()));
        fragmentTitles.add(Page1Fragment.class.getSimpleName());
        fragments.add(Fragment.instantiate(this, Page2Fragment.class.getName()));
        fragmentTitles.add(Page2Fragment.class.getSimpleName());
        fragments.add(Fragment.instantiate(this, Page3Fragment.class.getName()));
        fragmentTitles.add(Page3Fragment.class.getSimpleName());
       
        mViewPager = (ViewPager) findViewById(R.id.pager);
        View pagerStrip = findViewById(R.id.pagerTabStrip);
        if (pagerStrip instanceof PagerTabStrip) {
                PagerTabStrip pagerTabStrip = (PagerTabStrip) pagerStrip;
                pagerTabStrip.setDrawFullUnderline(true);
                pagerTabStrip.setTabIndicatorColorResource(android.R.color.black);
                // pagerTabStrip.setTextColor(color.white);
        } else if (pagerStrip instanceof PagerTitleStrip) {
                PagerTitleStrip pagerTitleStrip = (PagerTitleStrip) pagerStrip;
                pagerTitleStrip.setTextColor(getResources().getColor(android.R.color.white));
        }
        this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments, fragmentTitles);
        mViewPager.setAdapter(this.mPagerAdapter);
        mViewPager.setCurrentItem(0);
   }

Nel caso di "Tab Strip", possiamo abilitare un'effetto "selected" lasciando a true la proprietà setDrawFullUnderline; questo effetto può anche avere un colore diverso grazie al metodo setTabIndicatorColorResource(c'è anche la variante che accetta direttamente il colore).
E' poi possibile cambiare a runtime il colore del testo nei tab.
In caso di scelta del titleStrip, avremo meno attributi da cambiare, in particolare, il colore del testo (come da esempio).

La classe PagerAdapter è poco differente da quella presa dal tutorial di bradipao, se non per il metodo  getPageTitle, che serve appunto per renderizzare i testi nella strip.
Codice (Java): [Seleziona]
        @Override
        public CharSequence getPageTitle(int position) {

                if (null == fragmentTitles || fragmentTitles.size() <= position) {
                        return "unknown";
                }
                String fragTitle = fragmentTitles.get(position);
                if (null == fragTitle || fragTitle.trim().length() == 0) {
                        return "No Title";
                }
                // Log.v("TitleAdapter - getPageTitle=", fragmentTitles.get(position));
                return fragmentTitles.get(position);
        }

Ed ora, un paio di screenshot per mostrarvi i risultati:

Con PagerTabStrip:


Con PagerTitleStrip:

IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:[medio] ViewPager con tabs interattivi
« Risposta #1 il: 21 Luglio 2012, 07:24:57 CEST »
0
Bello!  :-)

Lo userò nella prossima app.  :-P
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Vlad

  • Utente normale
  • ***
  • Post: 271
  • Respect: +16
    • Github
    • Google+
    • vmihalachi
    • vmihalachi
    • Mostra profilo
    • vmihalachi.com
  • Dispositivo Android:
    Samsung galaxy s2 | Samsung galaxy tab 7
  • Play Store ID:
    Vlad Mihalachi
  • Sistema operativo:
    Windows 8
Re:[medio] ViewPager con tabs interattivi
« Risposta #2 il: 21 Luglio 2012, 09:09:29 CEST »
0
Ci credi se ti dico che lo stavo cercando propio adesso :D Thanks meritato !  :-)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #3 il: 21 Luglio 2012, 12:34:44 CEST »
0
Grazie a entrambi, ma il thanks maggiore va a bradipao, senza il suo tutorial non avrei fatto nulla, ero troppo pigro per capire per bene i fragments :D

Hai notato l'icona bradipao? ;)
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3487
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[medio] ViewPager con tabs interattivi
« Risposta #4 il: 21 Luglio 2012, 12:56:22 CEST »
0
Comunque con l'adt20 si può fare una cosa del genere (ovvero con PagerTitleStrip) semplicemente con il wizard di creazione dell'Activity. E in 3 minuti contati si possono cambiare gli import con quelli di ActionBarSherlock per garantire la retrocompatibilità ;)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #5 il: 21 Luglio 2012, 15:20:18 CEST »
0
Comunque con l'adt20 si può fare una cosa del genere (ovvero con PagerTitleStrip) semplicemente con il wizard di creazione dell'Activity. E in 3 minuti contati si possono cambiare gli import con quelli di ActionBarSherlock per garantire la retrocompatibilità ;)
eccolo, aspettavo il tuo commento :D
Avevo provato con l'adt20 a fare quello che dici ma c'era un bug e non faceva l'import corretto, ho letto su G+ che con l'adt 20.0.1 hanno corretto. Però il tutorial rimane sempre valido per capire chi fa cosa :D
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3487
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[medio] ViewPager con tabs interattivi
« Risposta #6 il: 21 Luglio 2012, 15:52:39 CEST »
0
eccolo, aspettavo il tuo commento :D
Avevo provato con l'adt20 a fare quello che dici ma c'era un bug e non faceva l'import corretto, ho letto su G+ che con l'adt 20.0.1 hanno corretto. Però il tutorial rimane sempre valido per capire chi fa cosa :D

Io l'avevo fatto correttamente anche con il 20. Comunque ovviamente non volevo sminuire il tuo tutorial, era solo per dire l'esistenza di uno shortcut :P Poi ovviamente bisogna capire cosa viene creato ;)

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #7 il: 22 Luglio 2012, 22:55:55 CEST »
0
Io l'avevo fatto correttamente anche con il 20. Comunque ovviamente non volevo sminuire il tuo tutorial, era solo per dire l'esistenza di uno shortcut :P Poi ovviamente bisogna capire cosa viene creato ;)
no problem, ne avevamo già parlato :D
Magari appena ho un attimo di tempo espando e provo a farlo direttamente da eclipse, cosi abbiamo le due versioni...
Questo credo sia più comodo per aggiungierlo ad un progetto esistente, l'altro funziona solo con nuove activity :D
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:[medio] ViewPager con tabs interattivi
« Risposta #8 il: 23 Luglio 2012, 08:33:13 CEST »
0
Magari appena ho un attimo di tempo espando e provo a farlo direttamente da eclipse, cosi abbiamo le due versioni...
Questo credo sia più comodo per aggiungierlo ad un progetto esistente, l'altro funziona solo con nuove activity :D

Io sono per i tutorial sul framework Android, poi una volta capito questo passare alla generazione automatica è banale.  :-P

NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline crc_error

  • Utente junior
  • **
  • Post: 85
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    LG-P500
  • Sistema operativo:
    Windows 8, Ubuntu 12
Re:[medio] ViewPager con tabs interattivi
« Risposta #9 il: 29 Marzo 2013, 13:13:30 CET »
0
Bel tutorial :)

Rispolvero il 3d perchè avrei una domandina a riguardo e non so se è il caso di aprirne uno nuovo...

E' possibile aggiornare il contenuto di tutti i fragment contemporaneamente direttamente dall'activity?

Mi spiego meglio. Nell'activity ho messo un broadcast receiver in "ascolto" su aggiornamenti inviati da un service.
Quello che vorrei fare, è inviare i dati ricevuti nell'activity ai fragment.

Per ora ho risolto implementando all'activity, le interfacce create nei 2 fragment e, ad ogni nuovo dato in arrivo dall'activity, vengono chiamati i metodi per aggiornare i fragment.

Ho abbozzato la una soluzione, ma non sono sicuro, anzi, non lo sono per niente, che sia il metodo corretto e più performante.
C'è un metodo migliore per aggiornare i dati?

Gli XML sono più o meno come i tuoi, non ho messo i pulsanti nei fragment ma solo una TextView (Che riceverà i dati) per ciascuno.

Ecco le mie modifiche:

Codice (Java): [Seleziona]
 public class TestApp extends FragmentActivity implements FragDati.OnPageListener, FragDati2.OnPageListener {

    //  ....
       
        @Override
        public void onFragDati(String datoB) {
                FragDati fDati = (FragDati) fragments.get(1);
                fDati.setValori(datoB);
        }

        @Override
        public void onFragDati2(String datoA) {
                FragDati2 fDati2 = (FragDati2) fragments.get(2);
                fDati2.setValori(datoA);
        }
 }

E nelle classi dei 2 fragment

FragDati
Codice (Java): [Seleziona]
    //  ....
        public interface OnPageListener {
                public void onFragDati(String datoAggiornato);
        }

        public void setValori(String datoAggiornato) {
          topLeft.setText(datoAggiornato);
        }

FragDati 2
Codice (Java): [Seleziona]
    //  ....
        public interface OnPageListener {
                public void onFragDati2(String datoAggiornato);
        }

        public void setValori(String datoAggiornato) {
          topLeft.setText(datoAggiornato);
        }
« Ultima modifica: 29 Marzo 2013, 13:15:21 CET da crc_error »

Offline Ormet

  • Utente junior
  • **
  • Post: 71
  • Respect: 0
    • Google+
    • Marco Falotico
    • Mostra profilo
  • Dispositivo Android:
    HTC One S
  • Play Store ID:
    Ormet
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #10 il: 19 Maggio 2013, 18:26:10 CEST »
0
Innanzitutto complimenti per il tutorial!
Una domanda: è possibile creare delle sub-pager?mi spiego meglio: vorrei per ogni pager crearne altri 2-3 sotto (per esempio pager 1 porta al avrà la possibilità di andare in 3 tab 1a, 1b, 1c, il 2 porterà ad altre 3 tab..) e possibile?spero di essermi spiegato..

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #11 il: 20 Maggio 2013, 09:40:16 CEST »
0
Innanzitutto complimenti per il tutorial!
Una domanda: è possibile creare delle sub-pager?mi spiego meglio: vorrei per ogni pager crearne altri 2-3 sotto (per esempio pager 1 porta al avrà la possibilità di andare in 3 tab 1a, 1b, 1c, il 2 porterà ad altre 3 tab..) e possibile?spero di essermi spiegato..
magari è anche possibile, ma te lo sconsiglio vivamente... ci sono tanti pattern per fare navigazione come la vuoi te,
io guarderei il nuovo navigation drawer:
Navigation Drawer | Android Developers
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline Ormet

  • Utente junior
  • **
  • Post: 71
  • Respect: 0
    • Google+
    • Marco Falotico
    • Mostra profilo
  • Dispositivo Android:
    HTC One S
  • Play Store ID:
    Ormet
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #12 il: 20 Maggio 2013, 12:41:55 CEST »
0
..ma ha bisogno di un sdk minimo di 11 o addirittura 14 se non sbaglio vero?l'avevo già visto e mi piace molto ma escludere gingerbread per adesso è ancora limitante secondo me..

Offline Nicola_D

  • Utente storico
  • *****
  • Post: 2479
  • SBAGLIATO!
  • Respect: +323
    • Github
    • Google+
    • nicoladorigatti
    • Mostra profilo
  • Dispositivo Android:
    Nexus 6p, Nexus 4, Nexus S, Nexus 7(2012)
  • Sistema operativo:
    Windows 7
Re:[medio] ViewPager con tabs interattivi
« Risposta #13 il: 20 Maggio 2013, 15:06:56 CEST »
0
..ma ha bisogno di un sdk minimo di 11 o addirittura 14 se non sbaglio vero?l'avevo già visto e mi piace molto ma escludere gingerbread per adesso è ancora limitante secondo me..
no no, fa parte della support lib v4, quindi lo puoi benissimo usare su gingerbread. Al massimo dovrai usare l'actionbarsherlock per vedere la barra sopra, ma ho visto che ci sono esempi di codice che usano le due cose
IMPORTANTE:NON RISPONDO A PROBLEMI VIA MESSAGGIO PRIVATO
LOGCAT: Non sai cos'è? -> Android Debug Bridge | Android Developers
               Dov'è in Eclipse? -> Window -> Open Prospective -> DDMS e guarda in basso!
[Obbligatorio] Logcat, questo sconosciuto! (Gruppo AndDev.it LOGTFO) - Android Developers Italia

Offline prezzemolo86

  • Nuovo arrivato
  • *
  • Post: 36
  • Respect: +1
    • Mostra profilo
Re:[medio] ViewPager con tabs interattivi
« Risposta #14 il: 20 Maggio 2013, 20:14:03 CEST »
+1
Ciao,
ho provato gli esempi, tanto questo quanto il precedente a cui si accenna ed sono ok. Grazie per avermi fatto capire il tutto. Ora però ho un problema: i miei fragment in pratica sono tutti uguali, mostrano un'immagine. Questa immagine viene presa facendo una richiesta al server. Per questo attivo un AsyncTask che ogni volta che reperisce l'immagine crea il Fragment e  lo inserisce nella List dell'adapter.
Purtroppo non vedo nulla :(

Mi viene il dubbio che non il il modo giusto per aggiornare il contenuto della lista dei fragment da mostrare