By Randy Sugianto 'Yuku'


2011-01-03 09:51:23 8 Comments

In Android applications such as Twitter (official app), when you encounter a ListView, you can pull it down (and it will bounce back when released) to refresh the content.

I wonder what is the best way, in your opinion, to implement that?

Some possibilities I could think of:

  1. An item on top of the ListView - however I don't think scrolling back to item position 1 (0-based) with animation on the ListView is an easy task.
  2. Another view outside the ListView - but I need to take care of moving the ListView position down when it is pulled, and I'm not sure if we can detect if the drag-touches to the ListView still really scroll the items on the ListView.

Any recommendations?

P.S. I wonder when the official Twitter app source code is released. It has been mentioned that it will be released, but 6 months has passed and we haven't heard about it since then.

15 comments

@Hasan Raza 2019-09-04 08:22:09

We should first know what is Pull to refresh layout in android . we can call pull to refresh in android as swipe-to-refresh. when you swipe screen from top to bottom it will do some action based on setOnRefreshListener.

Here's tutorial that demonstrate about how to implement android pull to refresh. I hope this helps.

@Randy Sugianto 'Yuku' 2014-04-01 13:06:56

Finally, Google released an official version of pull-to-refresh library!

It is called SwipeRefreshLayout, inside the support library, and the documentation is here:

  1. Add SwipeRefreshLayout as a parent of view which will be treated as pull to refresh layout. (I took ListView as an example, it can be any View like LinearLayout, ScrollView etc.)

    <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. Add a listener to your class

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

You can also call pullToRefresh.setRefreshing(true/false); as per your requirement.

@pablobaldez 2014-11-18 13:10:31

can I use a ProgressBar instead of Color Scheme on SwipeRefreshLayout?

@aeracode 2015-04-15 13:02:10

Apr 1 '14 - and that was not a joke

@Ayejuni Ilemobayo Kings 2019-08-11 22:38:24

thank, this works for me better

@Aracem 2012-06-14 10:11:18

In this link, you can find a fork of the famous PullToRefresh view that has new interesting implementations like PullTorRefreshWebView or PullToRefreshGridView or the possibility to add a PullToRefresh on the bottom edge of a list.

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

And the best of it is that work perfect in Android 4.1 (the normal PullToRefresh doesn't work )

@Milton 2013-05-09 13:10:19

A big comment at the top of the readme indicates: THIS PROJECT IS NO LONGER BEING MAINTAINED. Anyway, this lib is the best one I have seen so far! Great work!

@Muz 2013-06-02 07:17:27

Just because it's no longer being maintained, doesn't mean it's not good. Still use it for all my pull to refresh needs :)

@larrytech 2015-06-15 18:28:08

The easiest way i think is as provided by the android support library:

android.support.v4.widget.SwipeRefreshLayout;

once that is imported then you can have your layout defined as follows:

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

I assume that you use recycler view instead of listview. However, listview still works so you just need to replace recyclerview with listview and update the references in the java code (Fragment).

In your activity fragment, you first implement the interface, 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);

   }
}

Hope this helps the masses

@gabriel14 2015-11-10 08:30:07

It works well. Though, one thing regarding setRefreshing: "Do not call this when refresh is triggered by a swipe gesture" as described in developer.android.com/reference/android/support/v4/widget/…

@technik 2017-04-02 22:05:23

Good job! Thanks.

@mani 2015-05-20 08:51:10

To implement android Pull-to-Refresh try this piece of 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>

Activity class:

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

 }

@Arpan Sharma 2016-04-07 09:32:13

Thanks.it really helped me

@edbaev 2015-01-19 13:42:39

Very interesting Pull-to-Refresh by Yalantis. Gif for iOS, but you can check it :)

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

@goRGon 2014-11-19 20:34:45

To get the latest Lollipop Pull-To Refresh:

  1. Download the latest Lollipop SDK and Extras/Android support library
  2. Set Project's Build Target to Android 5.0 (otherwise support package can have errors with resources)
  3. Update your libs/android-support-v4.jar to 21st version
  4. Use android.support.v4.widget.SwipeRefreshLayout plus android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

Detailed guide could be found here: http://antonioleiva.com/swiperefreshlayout/

Plus for ListView I recommend to read about canChildScrollUp() in the comments ;)

@Petro 2015-03-25 21:10:42

Plus one just for mentioning canChildScrollUp(). Very important!

@Jossy Paul 2014-05-25 05:13:24

I think the best library is : https://github.com/chrisbanes/Android-PullToRefresh.

Works with:

ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager

@tomrozb 2013-12-21 11:10:31

Nobody have mention the new type of "Pull to refresh" which shows on top of the action bar like in the Google Now or Gmail application.

There is a library ActionBar-PullToRefresh which works exactly the same.

@uobroin 2012-11-01 20:12:02

Note there are UX issues to contend with when implementing on Android and WP.

"A great indicator for why designers/devs should not implement pull-to-refresh in the style iOS apps do is how Google and their teams never use pull-to-refresh on Android while they do use it in iOS. "

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

@ashishduh 2013-12-10 17:35:55

I know this is over a year old but the Gmail app does use pull-to-refresh. However it's not exactly the same in terms of the UI, the list does not scroll down, rather a new view shows at the top of the screen.

@Pushpan 2012-11-27 11:45:02

I have very easy way to do this but now sure its the foolproof way There is my 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;
    }
}

You just need to implement ListViewTouchEventListener on your activity where you want to use this ListView and set the listener

I have it implemented 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");
    }
}

It works for me :)

@Erik 2012-01-07 02:03:24

I've also implemented a robust, open source, easy to use and highly customizable PullToRefresh library for Android. You can replace your ListView with the PullToRefreshListView as described in the documentation on the project page.

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

@Gady 2012-03-16 16:13:18

I tried all of the implementations listed here and yours is the best, in terms of a simple/pure/smooth pull to refresh implementation (no tap to refresh weirdness like Johan's). Thanks!

@davidcesarino 2012-04-08 02:00:57

Can this replace a standard ListView to work with ListActivity, ListFragment and so on?

@Erik 2012-04-08 11:21:40

Yes, just give the PullToRefreshListView the right id. In XML: android:id="@android:id/list"

@Evan R. 2012-08-23 07:08:15

this is absolutely awesome! google brought me here, and looking through the examples, your's looks the easiest to implement. bravo and thank you sir!

@Adam 2012-12-03 04:17:47

Very sensibly designed component, nice and simple. This should definitely be the accepted answer.

@azizbekian 2012-12-05 15:54:46

@Erik, would you please tell, how can I change pull functionality to the bottom of ListView?

@StarDust 2013-02-19 10:11:36

This customization is great. Only drawback is my listview item is getting clicked when I try to refresh by pulling :(

@Nando 2013-06-02 17:46:28

Hi @Erik I'm testing your library and I have found a details on it. If there is another component(TextView, Button, etc) above the ListView, when you pull it down and release it the header view goes over your first component. This is what I'm talking about tinypic.com/r/72t5x1/5 Is there a way to fix this?

@Erik 2013-06-03 11:37:22

Hi Nando. Yes, the current workaround would be to wrap the ListView in a FrameLayout. I'm working on a more elegant fix. Thanks for your feedback. Erik

@AlvaroSantisteban 2013-07-31 08:30:33

It looks very good, but is it possible to use it replacing a ExpandableListView instead of a regular ListView?

@Akshat Agarwal 2013-11-06 19:02:29

@Erik I was having troubles using your library, could you help me at stackoverflow.com/questions/19820329/…

@Abx 2013-11-21 05:48:47

@Erik I found your library quite useful and simple.But I have problem in that ,I am not able to get the item click event when the screen is refreshing ,Any sujestion?

@Adam Johns 2014-04-17 15:26:51

Just a heads up if you use this with isitemchecked or setitemchecked - it appears index 0 of your listview will be reserved for the "refresh" area, so your first item will be index 1.

@Guille Polito 2011-07-30 20:05:21

I've written a pull to refresh component here: https://github.com/guillep/PullToRefresh It works event if the list does not have items, and I've tested it on >=1.6 android phones.

Any suggestion or improvement is appreciated :)

@Johan Berg Nilsson 2011-01-11 08:02:22

I've made an attempt to implement a pull to refresh component, it's far from complete but demonstrates a possible implementation, https://github.com/johannilsson/android-pulltorefresh.

Main logic is implemented in PullToRefreshListView that extends ListView. Internally it controls the scrolling of a header view using smoothScrollBy (API Level 8). The widget is now updated with support for 1.5 and later, please read the README for 1.5 support though.

In your layouts you simply add it like this.

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

@user577394 2011-01-16 15:18:37

Hi johan, I have downloaded your sample code. It is worked in android 2.2 device but not worked in 2.1 device. I think because it used smoothScrollBy method which only available in 2.2 or later, is correct? And do you have any idea to implement this effect into 2.1 or earlier version? Thanks

@Johan Berg Nilsson 2011-01-16 18:09:14

Yes that's correct as I stated in the answer smoothScrollBy was introduces in API Level 8 (2.2). I haven't figured out a proper way to implement it for other versions yet, but it guess it should be possible to port the implementation of smoothScrollBy but I guess that discussion should be kept at the project site and not on stack overflow?

@Mathias Conradt 2011-05-17 09:28:31

Is it on purpose that the id is @+id/android:list and not @android:id/list, it looks weird? The project throws an inflation error here on my side, I'm currently checking on that...

@Johan Berg Nilsson 2011-05-17 14:51:13

No it works fine with just @id/android:list too, it behaves just as a normal ListView would do. Errors like that is most likely because it's not set up as a library project.

@amsiddh 2011-10-01 13:11:21

Hi Johan, I have downloaded your sample code from above given link. But it doesn't have your library/jar to get "com.markupartist.android.widget.PullToRefreshListView, can you just give link for your lib also.

@Johan Berg Nilsson 2011-10-02 15:05:04

@amsiddh Only source is provided. Android library projects does not support jars, more details on how this works (and how this project is built) can be found here.

@Rainbowbreeze 2011-10-25 16:37:15

In addition to the great work made by @johan, I add a link to a post that clarify how to use and style its PullToRefreshListView: recursiveawesome.com/blog/2011/04/29/…

@rOrlig 2012-04-01 23:07:10

This is the best library for pull to refresh I have found..github.com/chrisbanes/Android-PullToRefresh. It works with ListViews, GridViews and Webviews. Also has Pull up to refresh pattern implemented.

@jowett 2012-05-10 03:57:41

Great, I have download the two projects and integrate them into one(I don't like the example-lib mode). It works well. The scroll state of listview can follow the gestures, thanks a lot

@Mustafa Güven 2013-01-14 12:35:09

How do I add the project into library folder while working on Intellij Idea? Can anybody help me?

@Zala Janaksinh 2014-06-18 10:42:50

Hell0 @JohanNilsson I implement your code for pull to refresh in my application, But one major issue I faced,When I select any row's item it's give the rong position,Like I select 5 row it's give me 6 the position, So my selection is not working properly ,So please if have any idea about this please post here.

@seema 2014-09-22 06:53:00

Hello @JohanNilsson When all data of list is visible at the time, then pull to refresh view doesn't hides completely. Can you suggest a fix for this?

@Lie Ryan 2011-01-05 14:34:28

If you don't want your program to look like an iPhone program that is force fitted into Android, aim for a more native look and feel and do something similar to Gingerbread:

alt text

@Lie Ryan 2011-02-26 12:42:39

@Rob: I meant having the orange shadow on the top of the list when you overpull, instead of having the list bounce back like on iPhone. This is meant as a comment (not answer), but comments can't have images.

@Rob 2011-03-01 12:00:39

Ahh, sorry, great Idea. I haven't played with gingerbread yet, so hadn't seen the effect. Still waiting for google to roll it to the nexus one.

@Thierry-Dimitri Roy 2011-04-18 15:19:51

I have Gingerbread and the orange glow works great when a list is static. But the pull-down-refresh is a great UI mecanism to refresh a dynamic list. Although it is prevalent in iOS world, it's a UI trick that doesn't feel wierd in Android ecosystem. I strongly suggest you check it out in the official Twitter app. :)

@steprobe 2012-04-20 17:58:27

The native behaviour here is to indicate that you have reached the end of a list. Taking this, and performing a refresh is identically non native as you are not doing what the platform does. This means you are more likely to surprise the user. I certainly wouldn't expect nor want a refresh just because I got to the end of a list. Pull down to refresh is a lot more intuitive and clear. And as the native twitter app uses it I think its fair to say it is a UI concept a large amount of people are familiar with.

Related Questions

Sponsored Content

97 Answered Questions

31 Answered Questions

11 Answered Questions

[SOLVED] Proper use cases for Android UserManager.isUserAGoat()?

48 Answered Questions

[SOLVED] Is there a unique Android device ID?

52 Answered Questions

38 Answered Questions

[SOLVED] How to lazy load of images in ListView in Android

25 Answered Questions

[SOLVED] Is there a way to run Python on Android?

39 Answered Questions

[SOLVED] How to get screen dimensions as pixels in Android

28 Answered Questions

[SOLVED] What is 'Context' on Android?

Sponsored Content