Come implementare Android Pull-to-Refresh


433

In applicazioni Android come Twitter (app ufficiale), quando si incontra un ListView, è possibile tirarlo giù (e tornerà indietro quando rilasciato) per aggiornare il contenuto.

Mi chiedo quale sia il modo migliore, secondo te, di implementarlo?

Alcune possibilità che mi vengono in mente:

  1. Un elemento in cima a ListView - tuttavia non credo che scorrere indietro alla posizione 1 (basata su 0) con l'animazione in ListView sia un compito facile.
  2. Un'altra vista al di fuori di ListView, ma devo occuparmi di spostare la posizione di ListView verso il basso quando viene estratta, e non sono sicuro di poter rilevare se i tocchi di trascinamento su ListView fanno ancora scorrere gli elementi su ListView.

Qualche consiglio?

PS Mi chiedo quando verrà rilasciato il codice sorgente dell'app Twitter ufficiale. È stato detto che uscirà, ma sono trascorsi 6 mesi e da allora non ne abbiamo più sentito parlare.


Questa funzionalità può essere implementata in un TableLayout creato dinamicamente. Per favore,
aiutatemi

github.com/fruitranger/PulltorefreshListView è un'altra mia implementazione. Supporto fluido e multi-touch.
Changwei Yao,

6
Correlati: "Pull-to-refresh": un modello anti UI su Android è un articolo che sostiene che questa UI non è qualcosa che dovrebbe essere usato su Android e ha suscitato molte discussioni sulla sua adeguatezza.
blahdiblah,

29
Qualcuno dovrebbe far sapere a Google perché l'ultima versione di Gmail per Android utilizza questo "modello anti".
Nick,

4
Pull to refresh è (ed è stato per un po ') un modello standard adottato in iOS e Android ed è molto naturale, quindi questa discussione anti-pattern è obsoleta. Gli utenti si aspetteranno di vederlo e di comportarsi come tale.
Martin Marconcini,

Risposte:


311

Infine, Google ha rilasciato una versione ufficiale della libreria pull-to-refresh!

Si chiama SwipeRefreshLayout, all'interno della libreria di supporto, e la documentazione è qui :

  1. Aggiungi SwipeRefreshLayoutcome genitore della vista che verrà trattato come un pull per aggiornare il layout. (Ho preso ListViewcome esempio, può essere qualsiasi Viewtipo LinearLayout, ScrollViewecc.)

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
  2. Aggiungi un ascoltatore alla tua classe

    protected void onCreate(Bundle savedInstanceState) {
        final SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);
        pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData(); // your code
                pullToRefresh.setRefreshing(false);
            }
        });
    }

Puoi anche chiamare pullToRefresh.setRefreshing(true/false);secondo le tue esigenze.

AGGIORNARE

Le librerie di supporto Android sono state deprecate e sono state sostituite da AndroidX. Il collegamento alla nuova biblioteca è disponibile qui .

Inoltre, è necessario aggiungere la seguente dipendenza al progetto:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

O

Puoi andare su Refactor >> Migrare ad AndroidX e Android Studio gestirà le dipendenze per te.


3
posso usare ProgressBar invece di Color Scheme su SwipeRefreshLayout?
pablobaldez,

54
1 aprile 14 - e non era uno scherzo
codice aereo


80

Ho tentato di implementare un componente pull to refresh, è tutt'altro che completo ma dimostra una possibile implementazione, https://github.com/johannilsson/android-pulltorefresh .

La logica principale è implementata in PullToRefreshListViewquesto modo ListView. Internamente controlla lo scorrimento di una vista dell'intestazione tramite smoothScrollBy(Livello API 8). Il widget è ora aggiornato con il supporto per 1.5 e versioni successive, si prega di leggere il supporto README per 1.5.

Nei tuoi layout lo aggiungi semplicemente in questo modo.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />

3
Ciao Johan, ho scaricato il tuo codice di esempio. Funziona con il dispositivo Android 2.2 ma non con il dispositivo 2.1. Penso che perché abbia usato il metodo smoothScrollBy che è disponibile solo in 2.2 o versioni successive, è corretto? E hai idea di implementare questo effetto nella versione 2.1 o precedente? Grazie

Sì, è corretto come ho affermato nella risposta smoothScrollBy è stato introdotto in API Level 8 (2.2). Non ho ancora trovato un modo corretto di implementarlo per altre versioni, ma immagino che dovrebbe essere possibile eseguire il porting dell'implementazione di smoothScrollBy ma immagino che la discussione dovrebbe essere mantenuta sul sito del progetto e non in overflow dello stack?
Johan Berg Nilsson,

È apposta che l'id è @ + id / android: list e non @android: id / list, sembra strano? Il progetto genera un errore di inflazione qui dalla mia parte, al momento sto verificando che ...
Mathias Conradt,

12
Questa è la migliore libreria per pull to refresh che ho trovato .. github.com/chrisbanes/Android-PullToRefresh . Funziona con ListViews, GridView e Webview. È inoltre implementato il pull up per aggiornare il modello.
rOrlig

1
Come faccio ad aggiungere il progetto nella cartella della libreria mentre lavoro su Intellij Idea? Qualcuno può aiutarmi?
Mustafa Güven,

55

Ho anche implementato una libreria PullToRefresh robusta, open source, facile da usare e altamente personalizzabile per Android. È possibile sostituire ListView con PullToRefreshListView come descritto nella documentazione nella pagina del progetto.

https://github.com/erikwt/PullToRefresh-ListView


Ho provato tutte le implementazioni elencate qui e la tua è la migliore, in termini di pull semplice / puro / liscio per aggiornare l'implementazione (nessun tocco per aggiornare le stranezze come quelle di Johan). Grazie!
Gady,

1
Questo può sostituire un ListView standard per funzionare con ListActivity, ListFragment e così via?
davidcsb,

Sì, basta dare a PullToRefreshListView l'id giusto. In XML: android: id = "@ android: id / list"
Erik

1
questo è assolutamente fantastico! google mi ha portato qui e, guardando gli esempi, il tuo sembra il più facile da implementare. bravo e grazie signore!
Evan R.,

Componente progettato in modo molto ragionevole, carino e semplice. Questa dovrebbe essere sicuramente la risposta accettata.
Adam,

42

Il modo più semplice penso sia fornito dalla libreria di supporto Android:

android.support.v4.widget.SwipeRefreshLayout;

una volta importato, è possibile definire il layout come segue:

  <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_height="match_parent"
        android:layout_width="match_parent">
    <android.support.v7.widget.RecyclerView
        xmlns:recycler_view="http://schemas.android.com/apk/res-auto"
        android:id="@android:id/list"
        android:theme="@style/Theme.AppCompat.Light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/button_material_light"
        >

    </android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

Presumo che tu usi la vista riciclatore anziché la vista elenco. Tuttavia, listview funziona ancora, quindi è sufficiente sostituire recyclerview con listview e aggiornare i riferimenti nel codice java (frammento).

Nel tuo frammento di attività, devi prima implementare l'interfaccia SwipeRefreshLayout.OnRefreshListener: i, e

public class MySwipeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
private SwipeRefreshLayout swipeRefreshLayout;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item, container, false);
        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);
        swipeRefreshLayout.setOnRefreshListener(this);
}


 @Override
  public void onRefresh(){
     swipeRefreshLayout.setRefreshing(true);
     refreshList();
  }
  refreshList(){
    //do processing to get new data and set your listview's adapter, maybe  reinitialise the loaders you may be using or so
   //when your data has finished loading, cset the refresh state of the view to false
   swipeRefreshLayout.setRefreshing(false);

   }
}

Spero che questo aiuti le masse


Funziona bene. Tuttavia, una cosa riguarda setRefreshing: "Non chiamarlo quando l'aggiornamento viene attivato da un gesto di scorrimento" come descritto in developer.android.com/reference/android/support/v4/widget/…
gabriel14

Buon lavoro! Grazie.
technik,

22

In questo link, puoi trovare un fork della famosa PullToRefreshvista che ha nuove implementazioni interessanti come PullTorRefreshWebViewo PullToRefreshGridViewo la possibilità di aggiungere un PullToRefreshbordo inferiore di un elenco.

https://github.com/chrisbanes/Android-PullToRefresh

E la cosa migliore è che funziona perfettamente in Android 4.1 (il normale PullToRefreshnon funziona)


3
Un grande commento nella parte superiore del readme indica: QUESTO PROGETTO NON È PIÙ MANTENUTO. Comunque, questa lib è la migliore che abbia mai visto finora! Ottimo lavoro!
Milton,

3
Solo perché non viene più mantenuto, non significa che non sia buono. Lo uso ancora per tutte le mie esigenze di aggiornamento :)
Muz

18

Ho un modo molto semplice per farlo, ma ora sono sicuro che sia il modo più sicuro. C'è il mio codice PullDownListView.java

package com.myproject.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

/**
 * @author Pushpan
 * @date Nov 27, 2012
 **/
public class PullDownListView extends ListView implements OnScrollListener {

    private ListViewTouchEventListener mTouchListener;
    private boolean pulledDown;

    public PullDownListView(Context context) {
        super(context);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        setOnScrollListener(this);
    }

    private float lastY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            lastY = ev.getRawY();
        } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
            float newY = ev.getRawY();
            setPulledDown((newY - lastY) > 0);
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isPulledDown()) {
                        if (mTouchListener != null) {
                            mTouchListener.onListViewPulledDown();
                            setPulledDown(false);
                        }
                    }
                }
            }, 400);
            lastY = newY;
        } else if (ev.getAction() == MotionEvent.ACTION_UP) {
            lastY = 0;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        setPulledDown(false);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    public interface ListViewTouchEventListener {
        public void onListViewPulledDown();
    }

    public void setListViewTouchListener(
            ListViewTouchEventListener touchListener) {
        this.mTouchListener = touchListener;
    }

    public ListViewTouchEventListener getListViewTouchListener() {
        return mTouchListener;
    }

    public boolean isPulledDown() {
        return pulledDown;
    }

    public void setPulledDown(boolean pulledDown) {
        this.pulledDown = pulledDown;
    }
}

Hai solo bisogno di implementare ListViewTouchEventListener sulla tua attività dove vuoi usare questo ListView e impostare il listener

L'ho implementato in PullDownListViewActivity

package com.myproject.activities;

import android.app.Activity;
import android.os.Bundle;

/**
 * @author Pushpan
 *
 */
public class PullDownListViewActivity extends Activity implements ListViewTouchEventListener {

    private PullDownListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        listView = new PullDownListView(this);
        setContentView(listView);
        listView.setListViewTouchListener(this);

        //setItems in listview
    }

    public void onListViewPulledDown(){
        Log.("PullDownListViewActivity", "ListView pulled down");
    }
}

Per me funziona :)


18

Per implementare Android Pull-to-Refresh prova questo pezzo di codice,

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</android.support.v4.widget.SwipeRefreshLayout>

Classe di attività:

ListView lv = (ListView) findViewById(R.id.lv);
SwipeRefreshLayout pullToRefresh = (SwipeRefreshLayout) findViewById(R.id.pullToRefresh);


lv.setAdapter(mAdapter);

pullToRefresh.setOnRefreshListener(new OnRefreshListener() {

        @Override
        public void onRefresh() {
            // TODO Auto-generated method stub

            refreshContent();

        }
    });



private void refreshContent(){ 

     new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                pullToRefresh.setRefreshing(false);
            }
        }, 5000);

 }

1
Thanks.it mi ha davvero aiutato
Arpan Sharma,

9

Nessuno ha menzionato il nuovo tipo di "Pull to refresh" che viene visualizzato nella parte superiore della barra delle azioni come nell'applicazione Google Now o Gmail.

C'è una libreria ActionBar-PullToRefresh che funziona esattamente allo stesso modo.


7

Nota che ci sono problemi UX da affrontare durante l'implementazione su Android e WP.

"Un ottimo indicatore del perché i progettisti / sviluppatori non dovrebbero implementare il pull-to-refresh nello stile delle app iOS è come Google e i loro team non usano mai il pull-to-refresh su Android mentre lo usano in iOS."

https://plus.google.com/109453683460749241197/posts/eqYxXR8L4eb


3
So che ha più di un anno, ma l'app Gmail utilizza pull-to-refresh. Tuttavia, non è esattamente lo stesso in termini di UI, l'elenco non scorre verso il basso, piuttosto una nuova vista mostra nella parte superiore dello schermo.
ashishduh,

4

Se non vuoi che il tuo programma assomigli a un programma per iPhone che è forzato su Android, punta a un aspetto più nativo e fai qualcosa di simile a Gingerbread:

testo alternativo


2
@Rob: intendevo avere l'ombra arancione in cima all'elenco quando si sovrappone, invece di far tornare indietro l'elenco come su iPhone. Questo si intende come un commento (non una risposta), ma i commenti non possono avere immagini.
Sdraiati Ryan il

Ah, scusa, ottima idea. Non ho ancora suonato con il pan di zenzero, quindi non ho visto l'effetto. Sto ancora aspettando che Google lo passi a quello del Nexus.
Rob

9
Ho Gingerbread e il bagliore arancione funziona alla grande quando un elenco è statico. Ma il pull-down-refresh è un ottimo meccanismo dell'interfaccia utente per aggiornare un elenco dinamico. Sebbene sia prevalente nel mondo iOS, è un trucco dell'interfaccia utente che non sembra strano nell'ecosistema Android. Ti consiglio vivamente di provarlo nell'app Twitter ufficiale. :)
Thierry-Dimitri Roy,

Il comportamento nativo qui è quello di indicare che hai raggiunto la fine di un elenco. Prendere questo ed eseguire un aggiornamento è identico non nativo in quanto non si sta facendo ciò che fa la piattaforma. Ciò significa che è più probabile che tu sorprenda l'utente. Certamente non mi aspetterei né desidererei un aggiornamento solo perché sono arrivato alla fine di un elenco. Tirare giù per aggiornare è molto più intuitivo e chiaro. E poiché l'app nativa di Twitter la usa, penso sia giusto dire che è un concetto di interfaccia utente con cui un sacco di persone hanno familiarità.
steprobe



1

Per ottenere l'ultimo aggiornamento pull-to di Lollipop:

  1. Scarica la più recente libreria di supporto per Lollipop SDK e Extras / Android
  2. Imposta il Target di costruzione del progetto su Android 5.0 (altrimenti il ​​pacchetto di supporto può contenere errori con le risorse)
  3. Aggiorna il tuo libs / android-support-v4.jar alla 21a versione
  4. Usa android.support.v4.widget.SwipeRefreshLayoutpiùandroid.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

La guida dettagliata è disponibile qui: http://antonioleiva.com/swiperefreshlayout/

Inoltre per ListView mi raccomando di leggere canChildScrollUp()nei commenti;)


Più uno solo per menzionare canChildScrollUp (). Molto importante!
Petro

1

Molto interessante Pull-to-Refresh di Yalantis . Gif per iOS, ma puoi controllarlo :)

<com.yalantis.pulltorefresh.library.PullToRefreshView
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
    android:id="@+id/list_view"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


0

Dovremmo prima sapere cos'è Pull per aggiornare il layout in Android. possiamo chiamare pull per aggiornare in Android come scorrere per aggiornare. quando scorri lo schermo dall'alto verso il basso, eseguirà alcune azioni in base a setOnRefreshListener.

Ecco tutorial che dimostrano come implementare Android Pull per aggiornare. Spero che questo possa essere d'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.