Android SwipeRefreshLayout Tutorial

In this post, we will describe Android SwipeRefreshLayout component. This component should be used whenever the user can refresh the UI using swipe gesture. In a previous post, we talked about another method to refresh the UI that we called shake to refresh, where the user shakes his smartphone and using accelerometer sensor the app refresh the UI. We talked about a custom implementation of this refresh pattern in this post where we implemented some like it.
The Android SwipeRefreshLayout component is a standard implementation provided by the SDK and it is already used in some App provided by Android (i.e Gmail).

Android swiperefreshlayout tutorial

Getting started with  Android SwipeRefreshLayout

Android SwipeRefreshLayout component accepts only one child: the component we want to refresh. It uses a listener mechanism to inform the listener that holds this component that a refresh event occurred, so in other word our Activity, for example, has to implement an interface to be notified. The Activity is responsible to handle the refresh event and refreshing the corresponding View. If the listener, once it receives the event, determines that the refresh process should take place and wants to show a “refresh animation”, it has to call setRefrshing(true), otherwise it can cancel the animation calling setRefreshing(false).

How to use SwipeRefreshLayout

Now we know how this component works, we will create a simple example to show how to use it. Let us suppose we want to generate a random number as the user uses a vertical swipe gesture:
android_swipetorefreshlayout

Usually this component is the root component:

<android.support.v4.widget.SwipeRefreshLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
android:id="@+id/swipe">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Random number:"
android:id="@+id/lbl"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/rndNum"
android:layout_toRightOf="@id/lbl"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/lbl"
android:layout_centerHorizontal="true"
android:layout_marginTop="20dp"
android:text="Swipe to Refresh"
style="@android:style/TextAppearance.Medium"/>

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

As you can see from the layout above, SwipeRefreshLayout has only one child. Now we can code our Activity:

...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe);
final TextView rndNum = (TextView) findViewById(R.id.rndNum);
swipeView.setColorScheme(android.R.color.holo_blue_dark, android.R.color.holo_blue_light, android.R.color.holo_green_light, android.R.color.holo_green_light);
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
Log.d("Swipe", "Refreshing Number");
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
double f = Math.random();
rndNum.setText(String.valueOf(f));
}
}, 3000);
}
});
}
....

As you can see everything in our example happens in onCreate method. At line 6 we get the reference to the SwipeRefreshLayout so that we can set the listener (line 10,11,12). In the listener we simply can setRefreshing(true) to enable to refreshing animation and then we generate our random number. At the end (we emulate a quite long process) we stop the animation.

SwipeRefreshLayout with ListView

Another interesting example is how to use SwipeRefreshLayout with a ListView. This is an interesting example because in real app we have often this situation where we have a ListView holding some items and we want to refresh them. If the ListView is the only one child of the SwipeRefreshLayout we wouldn’t have any kind of problems, because everything works smoothly. In some cases we have not only the ListView but we have other elements, let us suppose we have an UI like this:

android_swipetorefreshlayout_listview

This case is a little bit more complex, because if we scroll up the items in the ListView everything works as expected, but if the scroll down the refresh process starts and the list items doesn’t scroll as we want. In this case we can use a trick, we can disable the refresh notification using setEnabled(false) and enable it again as soon as the first item in the ListView is visible:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout) findViewById(R.id.swipe);

swipeView.setEnabled(false);
ListView lView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adp = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, createItems(40,0 ));
lView.setAdapter(adp);

swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);

}
}, 3000);
}
});

lView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {

}

@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0)
swipeView.setEnabled(true);
else
swipeView.setEnabled(false);
}
});
}

As you can see at line 33, we override the onScrollListener of the ListView to handle the enable/disable mechanism.

10 Comments

  1. Steve May 19, 2014
  2. survivingwithandroid May 20, 2014
  3. Steve May 20, 2014
  4. Matt June 19, 2014
  5. Guillaume Bourderye July 29, 2014
  6. Voldik January 7, 2015
  7. Keyur Lakhani March 5, 2015
  8. sreekar September 10, 2016
  9. PanharithHuot September 23, 2016

Add Comment