Autore Topic: Pull To Refresh List View, Aggiornamento in stile Twitter!  (Letto 6690 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
Pull To Refresh List View, Aggiornamento in stile Twitter!
« il: 21 Luglio 2011, 23:25:37 CEST »
+6
Livello di difficoltà: medio
Target SDK: 7
Min SDK: 5
Link al file compresso del progetto eclipse: file in allegato

Avete mai provato l'applicazione di twitter per android, o quella di facebook per iPhone? Vi è sempre piaciuto quel meccanismo di ricarica dei feeds trascinando la listview in basso? bene, qui vi mostro come fare....

Il progetto allegato sfrutta due risorse che devo assolutamente ringraziare:
1- johannilsson su github che è il vero realizzatore di questa tecnica
2- ricky per il suo script che genera i dati in formato json

Conoscenze richieste per questo tutorial?
JSON (Parsing e Struttura)
Handler (Thread & Message)
List View (conoscenze base)
Layouts (modifica)
String resources (funzionamento)
Formatting dates(tecnica)
Se non avete queste conoscenze, spolveratevele o imparatele, questo tutorial non vi spiegherà queste cose :D
Il json utilizzato qui, è un oggetto che contiene un dato che ci indica se ci sono altri elementi (qui non utilizzato), piu un'array di object, ogniuno formato da ID e Testo. Quindi l'esempio è molto semplice!

Cosa vuol dire pull to refresh?
Semplice, si capisce gia traducendo il termine letteralmente: "tira per aggiornare".
Come si usa? Ancora piu semplice! in caso di pochi elementi a video (listview che non "esce" dai limiti) verrà reso visibile un header che se premuto, richiamerà il refresh della listview (utilizzando un metodo da voi implementato).
In caso di molti elementi a video, l'header scompare (temporaneamente) per comparire solo se trascinate verso il basso la lista.
In questo caso, il testo dell'header cambierà indicandovi che, trascinando verso il basso la lista, questa verrà aggiornata. Rilasciando il touch, l'operazione di aggiornamento inizierà.

Di seguito il flow dell'applicazione; Si parte con lista vuota(a causa della modalità di funzionamento, si vedrà una voce "Tap to Refresh"), vengono scaricati i dati, aggiunti all'adapter, cosi da mostrarveli a schermo. Ora potete:
-Giocare con la lista (guardare gli elementi, cliccarli ecc)
-Fare il refresh della lista, semplicemente facendola scorrere verso il basso e seguendo le indicazioni (vedi foto allegate)

Per refreshare, invece dei soliti metodi con bottone in alto, tasto menu->Aggiorna, ora potete tirare la lista per richiamare il refresh(che in un caso realistico, può dare altri elementi)!



Implementare tutto questo, è veramente facile, modificarlo, un po meno...
Per prima cosa, prendete dai sorgenti la ListView modificata (PullToRefreshListView) ed inseritela nel vostro progetto (non vi spiegherò il funzionamento di questa classe, è molto complesso e lungo, prendetelo come oro colato)
Di seguito, vi serve una drawable per indicare l'operazione da fare (nel progetto, c'è una freccina che verrà automaticamente ruotata durante il trascinamento).
Ed infine, i layout:

quello principale dell'activity
Codice (XML): [Seleziona]
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
   <!-- The PullToRefreshListView replaces a standard ListView widget. -->
   <it.anddev.PullToRefreshListView
     android:id="@+id/android:list"
     android:layout_height="fill_parent"
     android:layout_width="fill_parent" />
</LinearLayout>

Quello dell'header:
Codice (XML): [Seleziona]
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:paddingTop="10dip"
  android:paddingBottom="15dip"
  android:gravity="center_vertical|center_horizontal"
  android:background="@drawable/pull_to_refresh_header_background">
   <RelativeLayout
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:gravity="center_vertical|center_horizontal">
      <ProgressBar
        android:id="@+id/pull_to_refresh_progress"
        android:indeterminate="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dip"
        android:layout_marginRight="20dip"
        android:layout_marginTop="10dip"
        android:visibility="gone"
        android:layout_centerVertical="true"
        style="?android:attr/progressBarStyleSmall" />
      <ImageView
        android:id="@+id/pull_to_refresh_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dip"
        android:layout_marginRight="20dip"
        android:visibility="gone"
        android:layout_gravity="center"
        android:gravity="center"
        android:src="@drawable/ic_pulltorefresh_arrow" />
      <TextView
        android:id="@+id/pull_to_refresh_text"
        android:text="@string/pull_to_refresh_tap_label"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textStyle="bold"
        android:paddingTop="5dip"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center" />
      <TextView
        android:id="@+id/pull_to_refresh_updated_at"
        android:layout_below="@+id/pull_to_refresh_text"
        android:visibility="visible"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center" />
   </RelativeLayout>
</LinearLayout>

Ed uno shape da inserire nella cartella drawable. Questo shape,rappresenta il background dell'header.
Nel progetto originale era bianco e la freccia nera, ho invertito i colori per mantenere il tema Black.
Codice (XML): [Seleziona]
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
    <gradient
       android:startColor="#121212"
       android:endColor="#000000"
       android:angle="-90" />
</shape>

Un unico permesso è richiesto (per il download dei dati):
Codice (XML): [Seleziona]
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
E alla fine, il codice!
Entriamo nella nostra activity e implementiamo la onCreate:
Codice (Java): [Seleziona]
// Impostiamo un listener che verrà richiamato ogni volta che l'utente fa il "tap" o il "pull".
                ((PullToRefreshListView) getListView()).setOnRefreshListener(new OnRefreshListener() {
                        @Override
                        public void onRefresh() {
                                // Richiamiamo il nostro metodo di refresh (download degli elementi)
                                callRefresh();
                        }
                });
//Impostiamo l'adapter personalizzato
                adapter = new FeedsListAdapter(getApplicationContext(), feeds);
                setListAdapter(adapter);
//Effettuiamo un primo download dei dati
                callRefresh();

Vi risparmio il codice di download e parsing (che è sempre il solito) e invece vi mostro, cosa si fa una volta ottenuta la risposta nell'handler:
Codice (Java): [Seleziona]
//I feeds mi vengono inseriti nell'oggetto del messaggio, quindi li prendo e li uso nel mio contenitore dati
        feeds = (ArrayList<Feed>) msg.obj;
//Richiamo la funzione di refresh
        refreshWholeList();
Ed eccoci alla parte se volete, piu interessante, il refresh della lista!
Codice (Java): [Seleziona]
//Imposto i feeds scaricati come dati per l'adapter
        adapter.setItems(feeds);
//Richiamo il metodo di callback della listview modificata
        ((PullToRefreshListView) getListView()).onRefreshComplete(String.format(getString(R.string.pull_to_refresh_last_update_label),sdf.format(new Date(System.currentTimeMillis()))));
Come potete vedere, il metodo accetta un parametro String,  chge altro non è che una stringa formattata che rappresenta il testo di "notifica" di ultimo update.
Nel mio caso il testo è:
Codice (XML): [Seleziona]
<string name="pull_to_refresh_last_update_label">Ultimo update: %s</string>Se vi chiedete cos'è sdf.format, vi dico subito che è un oggetto SimpleDateFormat, utile per formattare una data (nel mio caso, questo istante):
Codice (Java): [Seleziona]
private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Cosa manca? Ah si, i link d'esempio usato nel progetto:
Codice (Java): [Seleziona]
private String url = "http://anddev-rest.heroku.com/resources";
Questa è la seconda "feature" che mi serviva nel progetto fatto qualche mese fa, anche in questo caso il tutorial era in cantiere, ma il tempo è quello che è...
Spero di aver fatto cosa gradita a postare il tutorial, aspetto commenti, domande e discussioni costruttive!

Bibliografia:
« Ultima modifica: 21 Luglio 2011, 23:37:02 CEST da Nicola_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:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #1 il: 22 Luglio 2011, 07:56:09 CEST »
0
Effettivamente tutte le volte che apro twitter e aggiorno, penso sempre a come potrebbe essere realizzata una cosa del genere.

Continuerò a pensarci distrattamente, ma almeno so dove venire a leggere se voglio veramente farlo.  :-P
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

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:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #2 il: 22 Luglio 2011, 08:31:05 CEST »
0
Effettivamente tutte le volte che apro twitter e aggiorno, penso sempre a come potrebbe essere realizzata una cosa del genere.

Continuerò a pensarci distrattamente, ma almeno so dove venire a leggere se voglio veramente farlo.  :-P
lol! sempre qui a disposizione!!!
poi cmq quello di twitter secondo me è piu preciso, ma vabbe, li sono dipendenti, qui è passione... credo che qui ci sia piu che altro da fare tweaks sull'animazione della freccia ed il layout dell'header
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 mimmog

  • Utente senior
  • ****
  • Post: 731
  • Respect: +11
    • MisterX_Dev
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note e Galaxy Nexus
  • Play Store ID:
    MisterX_Dev
  • Sistema operativo:
    Windows 7
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #3 il: 16 Gennaio 2012, 16:39:16 CET »
0
Ottima  guida Nicola ! una sola domanda : se volessi fare un pull up to refresh per aggiornare la listview da sotto e non da sopra ??

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:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #4 il: 16 Gennaio 2012, 20:17:34 CET »
0
dovresti modificare la classe PullToRefreshListView in modo da farle utilizzare il footer invece che l'header... ora non ho il tempo materiale di controllare, ma dovrebbe essere relativamente semplice
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 mimmog

  • Utente senior
  • ****
  • Post: 731
  • Respect: +11
    • MisterX_Dev
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Note e Galaxy Nexus
  • Play Store ID:
    MisterX_Dev
  • Sistema operativo:
    Windows 7
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #5 il: 16 Gennaio 2012, 21:12:11 CET »
0
dovresti modificare la classe PullToRefreshListView in modo da farle utilizzare il footer invece che l'header... ora non ho il tempo materiale di controllare, ma dovrebbe essere relativamente semplice
Ok ci provo e ti faccio sapere ;)

Offline Ormet

  • Utente junior
  • **
  • Post: 73
  • Respect: 0
    • Google+
    • Marco Falotico
    • Mostra profilo
  • Dispositivo Android:
    HTC One S
  • Play Store ID:
    Ormet
  • Sistema operativo:
    Windows 7
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #6 il: 26 Marzo 2013, 13:19:28 CET »
0
ottimo tutorial!! domanda forse stupida, ma se io metto delle listview con dei dati (per esempio i risultati di delle partite) posso usare questo metodo per aggiornare le mie liste?

Offline blackgin

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1387
  • Respect: +164
    • Google+
    • blackgins
    • blackginsoft
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Nexus
  • Sistema operativo:
    Mac OSX 10.8
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #7 il: 26 Marzo 2013, 13:24:14 CET »
0
ottimo tutorial!! domanda forse stupida, ma se io metto delle listview con dei dati (per esempio i risultati di delle partite) posso usare questo metodo per aggiornare le mie liste?
Beh, se non con dati con cosa la vuoi riempire una ListView? :P
Ogni volta che fai il pull to refresh viene chiamato il metodo onRefresh()
Postate il LogCat LogCat LogCat LogCat LogCat

Offline Ormet

  • Utente junior
  • **
  • Post: 73
  • Respect: 0
    • Google+
    • Marco Falotico
    • Mostra profilo
  • Dispositivo Android:
    HTC One S
  • Play Store ID:
    Ormet
  • Sistema operativo:
    Windows 7
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #8 il: 26 Marzo 2013, 14:36:10 CET »
0
Forse ho spiegato male il mio dubbio..
Ho creato dei fragment che richiamano dei layout con all'interno le listview contenenti calendari e classifiche (aggiornati quindi non nel codice java ma nel layout)..
Usando questo metodo aggiorna questi layout ogni volta?

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:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #9 il: 26 Marzo 2013, 16:20:18 CET »
0
Forse ho spiegato male il mio dubbio..
Ho creato dei fragment che richiamano dei layout con all'interno le listview contenenti calendari e classifiche (aggiornati quindi non nel codice java ma nel layout)..
Usando questo metodo aggiorna questi layout ogni volta?
l'operazione è sulla listview,quindi se la tua listview sta in un fragment, si, si aggiorna anche quella
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: 73
  • Respect: 0
    • Google+
    • Marco Falotico
    • Mostra profilo
  • Dispositivo Android:
    HTC One S
  • Play Store ID:
    Ormet
  • Sistema operativo:
    Windows 7
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #10 il: 02 Aprile 2013, 07:31:11 CEST »
0
Wow! quindi cliccando questo bottone di refresh aggiornerà tutti i miei layout senza dover ogni volta aggiornare l'applicazione nel play store ad ogni mia modifica? Basterà fare uscire una nuova versione dell'applicazione nello store e lui automaticamente capirà dove e quali sono i dati da aggiornare? grazie mille per le delucidazioni datemi

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #11 il: 24 Giugno 2013, 21:07:30 CEST »
0
Ciao a tutti, sto usando la libreria di Chris Banes suggerita in questa guida. L'unico problema è che, una volta che aggiungo nuovi elementi alla mia lista, non riesco a posizionare il primo elemento nuovo della lista come primo elemento visibile. Ogni volta che aggiorno tutto funziona bene ma la lista scrolla sempre verso il primo elemento vecchio. Solitamente uso il metodo setSelection sulla lista, ma in questo caso non rientra nei metodi che posso utilizzare. Qualcuno ha qualche idea? Ps: gli elementi della lista sono di 4 tipi diversi, quindi credo che sarebbe non performante calcolare ogni volta la somma delle dimensioni degli elementi vecchi e usare lo scrollTo(x,y) sulla lista. Grazie

Offline elfo83

  • Utente normale
  • ***
  • Post: 283
  • Respect: +23
    • Mostra profilo
  • Sistema operativo:
    Mac OS 10.8.2
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #12 il: 06 Luglio 2013, 17:19:21 CEST »
0
Per chi è interessato, ho risolto aggiungendo questo metodo nella classe PullToRefreshListView e l'ho richiamato nella mia classe dopo aver aggiornato la lista con onRefreshComplete():

Codice (Java): [Seleziona]
public void scrollNewItem(int position)
        {
                mRefreshableView.setSelection(position);
        }

Offline djdedo

  • Utente normale
  • ***
  • Post: 209
  • Respect: +15
    • Mostra profilo
  • Dispositivo Android:
    Galaxy S2
Re:Pull To Refresh List View, Aggiornamento in stile Twitter!
« Risposta #13 il: 30 Settembre 2013, 18:15:54 CEST »
0
Ciao, ho scaricato il tuo progetto ma non scrolla proprio, nemmeno la lista normalmente. Devo modificare qualcosa? Dovrei implementare un effetto del genere sulla mia app e volevo vedere quale fosse l'effetto finale. Grazie