Comment implémenter Android Pull-to-Refresh

433

Dans les applications Android telles que Twitter (application officielle), lorsque vous rencontrez un ListView, vous pouvez le tirer vers le bas (et il rebondira lorsqu'il sera publié) pour actualiser le contenu.

Je me demande quelle est la meilleure façon, à votre avis, de mettre cela en œuvre?

Quelques possibilités auxquelles je pourrais penser:

  1. Un élément au-dessus de ListView - mais je ne pense pas que revenir à la position 1 de l'élément (basé sur 0) avec une animation sur ListView soit une tâche facile.
  2. Une autre vue en dehors de ListView - mais je dois prendre soin de déplacer la position de ListView vers le bas lorsqu'elle est tirée, et je ne suis pas sûr si nous pouvons détecter si les touches de glisser vers ListView font toujours vraiment défiler les éléments sur ListView.

Des recommandations?

PS Je me demande quand le code source officiel de l'application Twitter sera publié. Il a été mentionné qu'il serait publié, mais 6 mois se sont écoulés et nous n'en avons plus entendu parler depuis.

Randy Sugianto «Yuku»
la source
Cette fonctionnalité peut-elle être implémentée dans un TableLayout créé dynamiquement? S'il vous plaît, aidez .....
Arun Badole
github.com/fruitranger/PulltorefreshListView est une autre implémentation de la mienne. Prise en charge fluide et multi-touch.
Changwei Yao
6
Connexes: «Pull-to-refresh»: un modèle anti-interface utilisateur sur Android est un article faisant valoir que cette interface utilisateur n'est pas quelque chose qui devrait être utilisé sur Android et a suscité beaucoup de discussions sur sa pertinence.
blahdiblah
29
Quelqu'un devrait en informer Google, car la dernière version de Gmail pour Android utilise cet "anti-schéma".
Nick
4
Tirer pour actualiser est (et a été pendant un certain temps) un modèle standard adopté dans iOS et Android et c'est très naturel, donc cette discussion anti-modèle est obsolète. Les utilisateurs s'attendront à le voir et à se comporter comme tel.
Martin Marconcini

Réponses:

312

Enfin, Google a publié une version officielle de la bibliothèque pull-to-refresh!

Il est appelé SwipeRefreshLayout, à l'intérieur de la bibliothèque de support, et la documentation est ici :

  1. Ajouter en SwipeRefreshLayouttant que parent de vue qui sera traité comme un pull pour rafraîchir la mise en page. (J'ai pris ListViewcomme exemple, ça peut être Viewcomme ça LinearLayout, ScrollViewetc.)

    <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. Ajoutez un auditeur à votre 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);
            }
        });
    }
    

Vous pouvez également appeler pullToRefresh.setRefreshing(true/false);selon vos besoins.

MISE À JOUR

Les bibliothèques de support Android sont obsolètes et ont été remplacées par AndroidX. Le lien vers la nouvelle bibliothèque se trouve ici .

De plus, vous devez ajouter la dépendance suivante à votre projet:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

OU

Vous pouvez aller dans Refactor >> Migrer vers AndroidX et Android Studio gérera les dépendances pour vous.

Randy Sugianto «Yuku»
la source
3
puis-je utiliser un ProgressBar au lieu d'un jeu de couleurs sur SwipeRefreshLayout?
pablobaldez
54
1 avril 14 - et ce n'était pas une blague
aeracode
80

J'ai essayé d'implémenter un composant pull to refresh, il est loin d'être complet mais montre une implémentation possible, https://github.com/johannilsson/android-pulltorefresh .

La logique principale est implémentée dans PullToRefreshListViewcette extension ListView. En interne, il contrôle le défilement d'une vue d'en-tête à l'aide de smoothScrollBy(API niveau 8). Le widget est maintenant mis à jour avec la prise en charge de la version 1.5 et ultérieure, veuillez lire le fichier README pour la prise en charge 1.5.

Dans vos mises en page, vous l'ajoutez simplement comme ceci.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />
Johan Berg Nilsson
la source
3
Salut johan, j'ai téléchargé votre exemple de code. Il fonctionne sur un appareil Android 2.2 mais pas sur un appareil 2.1. Je pense parce qu'il a utilisé la méthode smoothScrollBy qui n'est disponible qu'en 2.2 ou version ultérieure, est-ce correct? Et avez-vous une idée d'implémenter cet effet dans la version 2.1 ou antérieure? Merci
Oui, c'est correct, comme je l'ai dit dans la réponse que smoothScrollBy a introduite dans l'API niveau 8 (2.2). Je n'ai pas encore trouvé de moyen approprié de l'implémenter pour d'autres versions, mais il suppose qu'il devrait être possible de porter l'implémentation de smoothScrollBy mais je suppose que la discussion doit être conservée sur le site du projet et non sur le débordement de pile?
Johan Berg Nilsson
Est-ce exprès que l'id est @ + id / android: list et non @android: id / list, ça a l'air bizarre? Le projet jette une erreur d'inflation ici de mon côté, je vérifie actuellement cela ...
Mathias Conradt
12
C'est la meilleure bibliothèque de pull pour rafraîchir que j'ai trouvée. Github.com/chrisbanes/Android-PullToRefresh . Il fonctionne avec ListViews, GridViews et Webviews. Le modèle Pull up to refresh a également été implémenté.
rOrlig
1
Comment ajouter le projet dans le dossier de la bibliothèque tout en travaillant sur Intellij Idea? Quelqu'un peut-il m'aider?
Mustafa Güven
55

J'ai également implémenté une bibliothèque PullToRefresh robuste, open source, facile à utiliser et hautement personnalisable pour Android. Vous pouvez remplacer votre ListView par le PullToRefreshListView comme décrit dans la documentation sur la page du projet.

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

Erik
la source
J'ai essayé toutes les implémentations répertoriées ici et la vôtre est la meilleure, en termes de traction simple / pure / fluide pour actualiser l'implémentation (pas de pression pour actualiser l'étrangeté comme celle de Johan). Merci!
Gady
1
Cela peut-il remplacer un ListView standard pour fonctionner avec ListActivity, ListFragment et ainsi de suite?
davidcsb
Oui, donnez juste à PullToRefreshListView le bon identifiant. En XML: android: id = "@ android: id / list"
Erik
1
c'est absolument génial! Google m'a amené ici, et en regardant les exemples, le vôtre semble le plus facile à mettre en œuvre. bravo et merci monsieur!
Evan R.
Composant très judicieusement conçu, agréable et simple. Cela devrait certainement être la réponse acceptée.
Adam
42

Je pense que la façon la plus simple est fournie par la bibliothèque de support Android:

android.support.v4.widget.SwipeRefreshLayout;

une fois importé, vous pouvez définir votre mise en page comme suit:

  <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>

Je suppose que vous utilisez la vue recycleur au lieu de la vue liste. Cependant, listview fonctionne toujours, il vous suffit donc de remplacer recyclerview par listview et de mettre à jour les références dans le code java (Fragment).

Dans votre fragment d'activité, vous implémentez d'abord l'interface,: SwipeRefreshLayout.OnRefreshListeneri, 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);

   }
}

J'espère que cela aide les masses

larrytech
la source
Ça marche bien. Cependant, une chose concernant setRefreshing: "N'appelez pas cela lorsque l'actualisation est déclenchée par un geste de balayage" comme décrit dans developer.android.com/reference/android/support/v4/widget/…
gabriel14
Bon travail! Merci.
technik
22

Dans ce lien, vous pouvez trouver un fork de la fameuse PullToRefreshvue qui a de nouvelles implémentations intéressantes comme PullTorRefreshWebViewou PullToRefreshGridViewou la possibilité d'ajouter un PullToRefreshsur le bord inférieur d'une liste.

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

Et le meilleur, c'est que le travail est parfait dans Android 4.1 (la normale PullToRefreshne fonctionne pas)

Aracem
la source
3
Un gros commentaire en haut du readme indique: CE PROJET N'EST PLUS MAINTENU. Quoi qu'il en soit, cette bibliothèque est la meilleure que j'ai vue jusqu'à présent! Bon travail!
Milton
3
Ce n'est pas parce que ce n'est plus entretenu que ce n'est pas bon. Utilisez-le toujours pour tous mes besoins de rafraîchissement :)
Muz
18

J'ai un moyen très simple de le faire, mais maintenant je suis sûr que c'est la méthode infaillible. Il y a mon code 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;
    }
}

Vous avez juste besoin d'implémenter ListViewTouchEventListener sur votre activité où vous souhaitez utiliser ce ListView et définir l'écouteur

Je l'ai implémenté dans 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");
    }
}

Ça marche pour moi :)

Pushpan
la source
18

Pour implémenter Android Pull-to-Refresh, essayez ce morceau de code,

<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 d'activité:

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);

 }
mani
la source
1
Thanks.it m'a vraiment aidé
Arpan Sharma
9

Personne n'a mentionné le nouveau type de "Pull to refresh" qui s'affiche en haut de la barre d'action comme dans l'application Google Now ou Gmail.

Il existe une bibliothèque ActionBar-PullToRefresh qui fonctionne exactement de la même manière.

tomrozb
la source
7

Notez qu'il y a des problèmes UX à gérer lors de la mise en œuvre sur Android et WP.

"Un excellent indicateur pour expliquer pourquoi les concepteurs / développeurs ne devraient pas implémenter le pull-to-refresh dans le style des applications iOS est la façon dont Google et leurs équipes n'utilisent jamais le pull-to-refresh sur Android alors qu'ils l'utilisent dans iOS."

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

uobroin
la source
3
Je sais que cela fait plus d'un an, mais l'application Gmail utilise le pull-to-refresh. Cependant, ce n'est pas exactement la même chose en termes d'interface utilisateur, la liste ne défile pas vers le bas, mais une nouvelle vue s'affiche en haut de l'écran.
ashishduh
4

Si vous ne voulez pas que votre programme ressemble à un programme iPhone forcé dans Android, visez une apparence et une sensation plus natives et faites quelque chose de similaire à Gingerbread:

texte alternatif

Lie Ryan
la source
2
@Rob: Je voulais dire avoir l'ombre orange en haut de la liste lorsque vous dépassez, au lieu de faire rebondir la liste comme sur iPhone. Il s'agit d'un commentaire (et non d'une réponse), mais les commentaires ne peuvent pas contenir d'images.
Lie Ryan
Ahh, désolé, super idée. Je n'ai pas encore joué avec du pain d'épice, donc je n'avais pas vu l'effet. Toujours en attente de google pour le faire rouler sur le Nexus.
Rob
9
J'ai du pain d'épice et la lueur orange fonctionne très bien quand une liste est statique. Mais le rafraîchissement est un excellent mécanisme d'interface utilisateur pour rafraîchir une liste dynamique. Bien qu'il soit répandu dans le monde iOS, c'est une astuce d'interface utilisateur qui ne se sent pas bizarre dans l'écosystème Android. Je vous suggère fortement de le vérifier dans l'application Twitter officielle. :)
Thierry-Dimitri Roy
Le comportement natif ici est d'indiquer que vous avez atteint la fin d'une liste. Prendre cela et effectuer une actualisation est identiquement non natif car vous ne faites pas ce que fait la plate-forme. Cela signifie que vous êtes plus susceptible de surprendre l'utilisateur. Je ne m'attendrais certainement pas à un rafraîchissement simplement parce que je suis arrivé à la fin d'une liste. Tirer vers le bas pour rafraîchir est beaucoup plus intuitif et clair. Et comme l'application native Twitter l'utilise, je pense qu'il est juste de dire que c'est un concept d'interface utilisateur que beaucoup de gens connaissent.
steprobe
4

J'ai écrit un pull pour actualiser le composant ici: https://github.com/guillep/PullToRefresh Cela fonctionne si la liste ne contient pas d'éléments, et je l'ai testée sur> = 1,6 téléphones Android.

Toute suggestion ou amélioration est appréciée :)

Guille Polito
la source
1

Pour obtenir la dernière actualisation Pull-To Lollipop:

  1. Téléchargez le dernier SDK Lollipop et la bibliothèque de support Extras / Android
  2. Définissez la cible de construction de Project sur Android 5.0 (sinon le package de support peut avoir des erreurs avec les ressources)
  3. Mettez à jour vos libs / android-support-v4.jar vers la 21e version
  4. Utiliser android.support.v4.widget.SwipeRefreshLayoutplusandroid.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

Un guide détaillé peut être trouvé ici: http://antonioleiva.com/swiperefreshlayout/

De plus pour ListView, je recommande de lire canChildScrollUp()dans les commentaires;)

goRGon
la source
Plus un juste pour mentionner canChildScrollUp (). Très important!
Petro
1

Pull-to-Refresh très intéressant par Yalantis . Gif pour iOS, mais vous pouvez le vérifier :)

<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" />

edbaev
la source
0

Nous devons d'abord savoir ce qu'est Pull pour rafraîchir la mise en page dans Android. nous pouvons appeler pull pour rafraîchir dans android comme glisser-rafraîchir. lorsque vous faites glisser l'écran de haut en bas, il effectuera une action basée sur setOnRefreshListener.

Voici un didacticiel qui montre comment implémenter Android Pull pour actualiser. J'espère que ça aide.

Hasan Raza
la source