Ajouter un Pull To Refresh avec SwipeRefreshLayout

Envie d’ajouter un effet Pull To Refresh à votre ListView ? Et bien sachez qu’il existe un composant natif à Android permettant d’ajouter cette fonctionnalité !

Pour ceux qui ignore ce qu’est un Pull To Refresh, je vais vous le montrer en image :

pull_to_refresh
Il s’agit donc d’ajouter un événement à notre ListView, qui s’active lorsque l’utilisateur est en haut de la liste mais continue à scroller vers le bas.

Android Support V4

Avant de commencer à vous parler de cette vue, il faut que j’introduise une notion en Android : le support.

Comme vous pouvez le savoir, il existe une multitude de versions d’android, et à l’heure où je vous parle nous sommes sur Android Lolipop, qui est la 5ème édition d’Android. Chaque version apporte son lot de nouveautés, de vues et d’outils, embarqués dans sa nouvelle version du système d’exploitation installé sur nos smartphones. Le problème est qu’il est fréquent de devoir réaliser une application supportant plusieurs version (par exemple supporter android à partir de 2.3).

En plus d’ajouter ces composants dans les nouvelles versions d’Android, la firme les publie aussi dans des paquets nommés Support, qui ont pour role d’utiliser le composant système s’il est présent, ou de reproduire son comportement (il est donc embarqué dans cette librairie). Certains oseront dire que ça alourdit l’application, répondez leur que rien ne leur empêche de développer leur application en ne supportant que la dernière version d’Android, et donc de perdre la moitié des utilisateurs 😉

Utilisation

Nous allons donc commencer par importer cette librairie via Gradle :

compile 'com.android.support:support-v4:21.0.3'

L’utilisation se fait ensuite en 2 étapes, une partie dans le layout de notre écran, le reste dans notre code Java.
Je ne détaillerai pas comment se servir des ListView dans ce tutoriel, cependant vous pouvez regarder le précédent article consacré à ce sujet : http://tutos-android-france.com/listview-afficher-une-liste-delements/

Layout

Partons d’un Layout simple, ne contenant qu’une ListView :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</RelativeLayout>

Afin d’ajouter la fonctionnalité de Pull To Refresh, il suffit juste de placer notre ListView dans un objet nommé  SwipeRefreshLayout. Comme dit précédemment, cet objet est inclu dans la librairie Support V4, nous devons donc l’utiliser avec son préfixe complet android.support.v4.widget.SwipeRefreshLayout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

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

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

</RelativeLayout>

Ajoutez un adapter qui affiche des Strings pour visualiser plus facilement.

public class MainActivity extends ActionBarActivity {

    List<String> strings = new ArrayList<String>();

    ListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.listView);

        for(int i=0;i<20;++i)
            strings.add("Element "+i);

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, strings);
        mListView.setAdapter(adapter);
    }

}

Vous pouvez dès à présent essayer ce composant en compilant l’application et en le lançant sur votre smartphone.

 

swipeRefresh1 swipeRefresh2swipeRefresh3

Java

Vous aurez pu remarquer en testant le SwipeRefreshLayout qu’une fois cet element relâché, il tourne indéfiniment. En effet il faut qu’un contrôleur lui indique qu’il a finit de rafraichir le contenu de la ListView qu’il contient.

device-2015-03-01-173023

 

Comme toute vue, nous pouvons le récupérer notre avec son identifiant, avec la méthode findViewById

 

public class MainActivity extends ActionBarActivity {

    List<String> strings = new ArrayList<String>();

    ListView mListView;
    SwipeRefreshLayout mSwipeRefreshLayout;
    ArrayAdapter<String> mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.listView);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);

        for(int i=0;i<20;++i)
            strings.add("Element "+i);

        mAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, strings);
        mListView.setAdapter(mAdapter);
    }

}

Si nous regardons à la documentation officielle de cette vue, nous pouvons remarquer qu’elle possède les méthodes suivantes :

  • setColorSchemeColors(int… colors) : permet de modifier la couleur de la flèche qui tourne
  • setProgressBackgroundColor(int color) : permet de modifier la couleur de fond du cercle
  • setSize(int size) : permet de modifier la taille de notre flèche (DEFAULT ou LARGE)

Ces méthodes sont utilisées afin de modifier l’aspect de notre élément, mais intéressons nous plutôt au coté fonctionnel :

  • setRefreshing(true) : permet de lancer l’animation de mise à jour.
  • setRefreshing(false) : indique à la vue que le contenu de la ListView à été mise à jour
  • setOnRefreshListener(OnRefreshListener) : récupère les évènements lancés par notre SwipeRefreshLayout. Utilisé par notre Activity afin de savoir que l’utilisateur a effectué un SwipeToRefresh

Implémentons donc le OnRefreshListener dans notre Activity :

mSwipeRefreshLayout.setOnRefreshListener(this);
@Override
public void onRefresh() {
    //appellé lors de l'action Pull To Refresh
}

Je vais donc simuler une méthode longue comme un appel réseau qui aurait duré 2 secondes, ensuite ajouter des éléments à ma ListView puis indiquer à mon SwipeRefreshLayout que le la mise à jour a été effectuée . (Pour les puristes Android, il est préférable d’utiliser des AsyncTask)

Je vais simplement utiliser ici une méthode des vues nommée .PostDelayed(Runnable runnable, int delay) qui permet d’effectuer une action après delay millisecondes.

public class MainActivity extends ActionBarActivity implements SwipeRefreshLayout.OnRefreshListener {

    List<String> strings = new ArrayList<String>();

    ListView mListView;
    SwipeRefreshLayout mSwipeRefreshLayout;
    ArrayAdapter<String> mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.listView);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
        mSwipeRefreshLayout.setOnRefreshListener(this);

        for(int i=0;i<20;++i)
            strings.add("Element "+i);

        mAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, strings);
        mListView.setAdapter(mAdapter);
    }

    @Override
    public void onRefresh() {
        //appellé lors de l'action Pull To Refresh

        mSwipeRefreshLayout.postDelayed(new Runnable() {
            @Override
            public void run() {
                //appellé après 2000 ms

                //vide la liste
                strings.clear();

                //puis ajoute les nouveaux elements
                for(int i=0;i<20;++i)
                    strings.add("NouvelElement "+i);

                //annonce à l'adapter que les données ont changés
                mAdapter.notifyDataSetChanged();

                //avertie le SwipeRefreshLayout que la mise à jour a été effectuée
                mSwipeRefreshLayout.setRefreshing(false);
            }
        },2000);
    }
}

4 commentaire sur “Ajouter un Pull To Refresh avec SwipeRefreshLayout

  1. I will immediately grab your rss feed as I can not find your email subscription link or enewsletter service. Do you’ve any? Please let me know in order that I could subscribe. Thanks. gafkdcbfedkd

  2. Article fort sympathique, une lecture agréable. Ce blog est vraiment pas mal, et les sujets présents plutôt bons dans l’ensemble, bravo ! Virginie Brossard

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *