-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Implementing Pull to Refresh Guide
In Android, the common "pull to refresh" UX concept is not built in to a ListView. However, many Android applications would like to make use of this concept for their feeds. This is useful for all sorts of feeds such as a Twitter timeline. This effect can be achieved using either the SwipeRefreshLayout
from the support library, which was recently introduced and back-ported to all versions down to Android API level 4.
SwipeRefreshLayout is a ViewGroup that can hold only one scrollable view as a child. This can be either a ScrollView
or an AdapterView
such as a ListView
.
Note: This layout only exists within more recent versions of support-v4 as explained in this post. Edit your app/build.gradle
file to include a support library later than version 19:
apply plugin: 'com.android.application'
//...
dependencies {
// ...
compile 'com.android.support:support-v4:21.0.3'
}
You must download and use a recent jar of the support library for this to work.
We can use this by first wrapping the scrollable view with a SwipeRefreshLayout
in the XML layout:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swipeContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/lvItems"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" >
</ListView>
</android.support.v4.widget.SwipeRefreshLayout>
Next, we need to configure the SwipeRefreshLayout
during view initialization in the activity:
public class TimelineActivity extends Activity {
private SwipeRefreshLayout swipeContainer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swipeContainer);
// Setup refresh listener which triggers new data loading
swipeContainer.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
// Your code to refresh the list here.
// Make sure you call swipeContainer.setRefreshing(false)
// once the network request has completed successfully.
fetchTimelineAsync(0);
}
});
// Configure the refreshing colors
swipeContainer.setColorSchemeResources(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
public void fetchTimelineAsync(int page) {
client.getHomeTimeline(0, new JsonHttpResponseHandler() {
public void onSuccess(JSONArray json) {
// ...the data has come back, finish populating listview...
// Now we call setRefreshing(false) to signal refresh has finished
swipeContainer.setRefreshing(false);
}
public void onFailure(Throwable e) {
Log.d("DEBUG", "Fetch timeline error: " + e.toString());
}
});
}
}
Note that upon successful reload, we must also signal that the refresh has completed by calling setRefreshing(false)
.
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.