In this  tutorial I’ll show you how to use pull to refresh feature in your android application. Pull to refresh is the hottest android UI pattern used by developers in their applications to improve the usability. You can see this pull to refresh feature in many android applications  like Gmail,Facebook, Twitter etc…  I google it to find some tutorials to how implement this but I couldn’t find any article related to this topic. I did it my self.  For a beginner it may be a difficult task to do. So I thought to do tutorial on this topic which will help to people who is struggling to use pull to refresh in their android application.

Demo Video

Note :

At end of this tutorial you can download the example project and you can see the video demonstration of this tutorial which will help you to follow this tutorial step by step.

Things to Know Before Start

To implement android pull to refresh we need to use an external android library. There are two popular libraries called “Android-PullToRefresh” and “ActionBar-PullToRefresh”. Both libraries are developed by Chrisbanes. “Android-PullToRefresh” library is no longer maintained by developer (Library is Expired). So “ActionBar-PullToRefresh” library is the newest library maintaining by Chrisbanes. This tutorial will use “ActionBar-PullToRefresh” library.

“ActionBar-PullToRefresh” library will interact with  the application actionbar to refresh. This library also compatible with  “ActionBarSherlock”. In this tutorial I’ll not use “ActionBarSherlock” library behalf I’ll use stock android actionbar. This library default supports only for android 4.0 (ICS-API level 14) or higher sdk levels. If you need to use this library below API-Level 14 you need use ActionBarCompact  library. Check Android Pull To Refresh with ActionBarCompact “ article to learn how to do this.

As you can see in the demo video above “ActionBar-PullToRefresh” library  is support  different views. Below list will show you compatible views.

  • AbsListView derivatives (ListView & GridView).
  • ScrollView
  • WebView

In this article I’ll cover ListView,WebView & ScrollView implementation.

Okay, Lets Start…

Step 1 : Download Libraries

Download below libraries and extract it.

ActionBar-PullToRefresh : Download from Github

 SmoothProgressBar : Download from Github

Step 2 : Start the Project and Fixing Errors in Libraries

Create a new  android application project called “PullToRefreshExample“. It is important to select “API 14 Android 4.0 (ICS)” as application minimum required sdk. I’ll change the activity name to “ListViewActivity“.  Now you need to import both downloaded libraries to your workspace. After you extract both downloaded zip files import both “library” folders from “ActionBar-PullToRefresh-master” and “SmoothProgressBar-master” folders. If you don’t know how to import an existing project to your worksapce check this  “How to Import Android Project to Eclipse” video.

Package Explore screen shot
Errors in ActionBar Pull To Refresh Library

After you Import both libraries to your workspace ActionBar Pull To Refresh Library will have some errors as you can see in above image. In order to fix this errors you need to do some updates to both libraries.

Smooth Progress Bar Library Updates

By default this project will not be a library project. So you may not able to add this as reference to pull to refresh library.Follow below steps to  convert this project to a library.

  1. Right Click “main” project and goto “Properties”
  2. Go to “Android” section.
  3. Under library check whether “Is Library” check box is checked or not.
  4. If it is not checked. Check the “Is Library” check box.
  5. Click “OK” button

Next you need to Drag and Drop the “fr” folder from “java” to “src” folder  in “main” project.  By default all the class will be in “java” folder so you need to change it “src” folder.

Fixing smooth progress bar error - android pull to refresh
Drag and Drop the “fr” folder to “src”

ActionBar Pull to Refresh Library Updates

Add the “SmoothProgressBar” library as reference to “ActionBar Pull To Refresh ” Library. Follow below steps to do it.

  1. Right click  “library” project and goto “Properties”
  2. Go to “Android” section
  3. Unde “Library” click “Add” button
  4. From “Project Selection” window select the “main” project
  5. Click “OK” button
  6. Click “OK” button to close the property window

Next open the “AndroidManifest.xml” file of ActionBar pull to refresh library. Update the manifest file as below

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="uk.co.senab.actionbarpulltorefresh.library">

    <!-- set the minimum sdk version to 11 -->
     <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="18" />

    <application />
</manifest>

Now most of the errors should be fixed. But there should error in “uk.co.senab.actionbarpulltorefresh.library => DefaultHeaderTransformer.java” class like below which will tell you there is no width(int) method in “SmoothProgressDrawable” class.

ActionBar pull to refresh error
Error in width() method

To fix this error you need to simply change the width(strokeWidth) to strokeWidth(strokeWidth).  Now all the errors are fixed.

Step 3 : Use ActionBar Pull To Refresh Library

Now you need to add “ActionBar-PullToRefresh” library as reference your application. Follow below steps to do it.

  1. Right click  “PullToRefreshExample” project and goto “Properties”
  2. Go to “Android” section
  3. Unde “Library” click “Add” button
  4. From “Project Selection” window select the “library” project
  5. Click “OK” button
  6. Click “OK” button to close the property window

Create a  class called “BaseActivity“. This is the base activity class used for all other supported views (Listview,WebView,ScrollView).  BaseActivity class should extend Activity class. Add following code to the BaseActivity class. I have commented the code so you can  read and understand the code.

package com.tutecentral.pulltorefreshexample;

import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class BaseActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);

        // Add the Sample Fragment if there is one
        Fragment sampleFragment = getSampleFragment();
        if (sampleFragment != null) {
            getFragmentManager().beginTransaction()
                    .replace(android.R.id.content, sampleFragment).commit();
        }

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub

		  getMenuInflater().inflate(R.menu.base_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		// This method is for menu. This menu items will appear in all
		//activities extends this class. I have use this menus to navigate
		//between activities. You can change this code as you wish
		//

		  switch (item.getItemId()) {
          case R.id.action_listview:
              Toast.makeText(this, "Pull to Refresh in ListView", Toast.LENGTH_SHORT).show();
              Intent i=new Intent(this,ListViewActivity.class);
              startActivity(i);

              return true;
          case R.id.action_scrollview:
              Toast.makeText(this, "Pull to Refresh in Scroll View", Toast.LENGTH_SHORT).show();

              Intent x=new Intent(this,ScrollViewActivity.class);
              startActivity(x);

              return true;
          case R.id.action_webview:
              Toast.makeText(this, "Pull to Refresh in Web View", Toast.LENGTH_SHORT).show();

              Intent z=new Intent(this,WebViewActivity.class);
              startActivity(z);

              return true;
      }

		return super.onOptionsItemSelected(item);
	}

	//This method will override by child class. Then base class can get the fragment
	protected Fragment getSampleFragment() {
        return null;
    }

}

Create an android xml file in “res =>menu” folder called “base_menu.xml“. Copy and paste the below code into the file. This menu used in BaseActivity to share the single  menu with all fragments.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
    You can change this as your requrement. I use this menu Item to navigate bettween
    fragments. So I can show how ListView,WebView & ScrollView works with
    ActionBar Pull To Refresh Library
      -->

    <item android:id="@+id/action_listview"
          android:title="ListView"
          android:showAsAction="ifRoom|withText" />

    <item android:id="@+id/action_webview"
          android:title="WebView"
          android:showAsAction="ifRoom|withText" />

        <item android:id="@+id/action_scrollview"
          android:title="ScrollVIew"
          android:showAsAction="ifRoom|withText" />

</menu>

Now BaseActivity class is completed. You will see errors in this class because I didn’t create “WebViewActivity” & “ScrollViewActivity” activities. These two activities are used to implement pull to refresh in web view and scroll view. If you are not using those views you can delete that code snippet from your BaseActivity.java class.

As I mention I will use this pull to refresh library in ListView,WebView and ScrollView. So I will start with ListView,

Pull To Refresh With ListView

Goto “res => layout” open the “activity_list_view.xml”  copy and paste the following code to xml file

<?xml version="1.0" encoding="utf-8"?>
<uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ptr_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

</uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout>

Now open the “ListViewActivity.java” class.This class will extend by BaseActivity. Update your ListViewActivity class according to below code or copy and paste below code your class.

package com.tutecentral.pulltorefreshexample;

import java.util.ArrayList;
import java.util.List;

import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout;
import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Fragment;
import android.app.ListFragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

public class ListViewActivity extends BaseActivity {

	@Override
	 protected Fragment getSampleFragment() {
	        return new SimpleListFragment();
	    }

	public static class SimpleListFragment extends ListFragment implements OnRefreshListener
	{

		int i=0;

	private	PullToRefreshLayout mPullToRefreshLayout;

	ArrayAdapter<String> adapter;

	List<String> list;

		@Override
		public void onViewCreated(View view, Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onViewCreated(view, savedInstanceState);

			list=new ArrayList<String>();
			int no=1;
			for(int i=0;i<5;i++)
			{
				list.add("Item No :"+no++);
			}

			  super.onViewCreated(view,savedInstanceState);
	            ViewGroup viewGroup = (ViewGroup) view;

	            // As we're using a ListFragment we create a PullToRefreshLayout manually
	            mPullToRefreshLayout = new PullToRefreshLayout(viewGroup.getContext());

	            // We can now setup the PullToRefreshLayout
	            ActionBarPullToRefresh.from(getActivity())
	                    // We need to insert the PullToRefreshLayout into the Fragment's ViewGroup
	                    .insertLayoutInto(viewGroup)
	                    // Here we mark just the ListView and it's Empty View as pullable
	                    .theseChildrenArePullable(android.R.id.list, android.R.id.empty)
	                    .listener(this)
	                    .setup(mPullToRefreshLayout);

		}

		@Override
		public void onActivityCreated(Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onActivityCreated(savedInstanceState);

			adapter=new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, list);

		    // Set the List Adapter to display the sample items
            setListAdapter(adapter);
            setListShownNoAnimation(true);
		}

		@Override
		public void onRefreshStarted(View view) {
			// TODO Auto-generated method stub

			//setListShown(false); // This will hide the listview and visible a round progress bar

			 new AsyncTask<Void, Void, Void>() {

	                @Override
	                protected Void doInBackground(Void... params) {
	                    try {
	                        Thread.sleep(5000); // 5 seconds
	                        int itemNo=list.size();
	                        itemNo++;
	                     list.add("New Item No :"+itemNo);

	                    } catch (InterruptedException e) {
	                        e.printStackTrace();
	                    }
	                    return null;
	                }

	                @Override
	                protected void onPostExecute(Void result) {
	                    super.onPostExecute(result);

	                    adapter.notifyDataSetChanged();
	                    // Notify PullToRefreshLayout that the refresh has finished
	                    mPullToRefreshLayout.setRefreshComplete();

	            // if you set the "setListShown(false)" then you have to
	            //uncomment the below code segment

//	                    if (getView() != null) {
//	                        // Show the list again
//	                        setListShown(true);
//	                    }
	                }
	            }.execute();

		}

	}

}

Now listview class is over. Currently you are not able to run this program because there are some errors in BaseActivity.java class to fix.  Just comment below lines and run the application to check the result.

...
  Intent x=new Intent(this,ScrollViewActivity.class); //comment this line
              startActivity(x);//comment this line

...
 Intent z=new Intent(this,WebViewActivity.class);//comment this line
              startActivity(z);//comment this line

Pull To Refresh With WebView

Now I’ll show you how to use this actionbar pull to refresh library with a webview. Create a new New Android Activity called “WebViewActivity“. Follow below steps to create new activity.

  1. Right click “src”  goto “New” then click “Others…”
  2. From “New” window select “Android Activity” under “Android” group and click “Next”
  3. Select “Blank Activity” as template and click “Next”
  4. Activity Name should be “WebViewActivity” and Layout Name should be “activity_web_view
  5. Then click “Finish” to create the activity

Now goto “res=>layout” open the “activity_web_view.xml” file. This file should include a “PullToRefreshLayout”  and a “WebView” as following code

<uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ptr="http://schemas.android.com/apk/res-auto"
    android:id="@+id/ptr_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        ptr:ptrViewDelegateClass="uk.co.senab.actionbarpulltorefresh.library.viewdelegates.WebViewDelegate" />

</uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout>

Now goto the “WebViewActivity.java” class and update the class according to below coding. This class extends “BaseActivity”  and implements “OnRefreshListener

package com.tutecentral.pulltorefreshexample;

import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout;
import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class WebViewActivity extends BaseActivity implements OnRefreshListener {

	 private PullToRefreshLayout mPullToRefreshLayout;

	    private WebView mWebView;

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

			 mWebView = (WebView) findViewById(R.id.webview);
		        mWebView.getSettings().setJavaScriptEnabled(true);
		        mWebView.setWebViewClient(new SampleWebViewClient());

		        // Now find the PullToRefreshLayout and set it up
		        mPullToRefreshLayout = (PullToRefreshLayout) findViewById(R.id.ptr_layout);
		        ActionBarPullToRefresh.from(this)
		                .allChildrenArePullable()
		                .listener(this)
		                .setup(mPullToRefreshLayout);

		        // Finally make the WebView load something...
		        mWebView.loadUrl("http://www.tutecentral.com");

		}

		@Override
		public void onRefreshStarted(View view) {
			// TODO Auto-generated method stub

			//////This method will Automatically call when
			/////pull to refresh event occurs

			  mWebView.reload();
		}

		  private class SampleWebViewClient extends WebViewClient {

		        @Override
		        public boolean shouldOverrideUrlLoading(WebView view, String url) {
		            // Return false so the WebView loads the url
		            return false;
		        }

		        @Override
		        public void onPageFinished(WebView view, String url) {
		            super.onPageFinished(view, url);

		            // If the PullToRefreshAttacher is refreshing, make it as complete
		            if (mPullToRefreshLayout.isRefreshing()) {
		                mPullToRefreshLayout.setRefreshComplete();
		            }
		        }
		    }

}

We need to Internet permission to render the webview. Add following permission code to application “AndroidManifest.xml” file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.tutecentral.pulltorefershexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.INTERNET" />

....

Pull To Refresh With ScrollView

Create a another android activity called “ScrollViewActivity” give Layout name as “activity_scroll_view“. In this activity I’ll use a Scroll View with Pull to Refresh Layout.  Open the    “activity_scroll_view.xml” file in your “layout” folder. add below xml to your layout.

I have used a “TextView” inside the ScrollView. You can use your own compatible android view with scroll view behalf of “TextView”

<uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ptr_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:id="@+id/scrollview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="8dp"
        android:scrollbarStyle="insideInset">

        <!-- Below TextView used to update the screen. You can use any
             android View with ScrollView.    -->
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Pull Down to Add More Text"
            android:id="@+id/scrollTextView"
            />

    </ScrollView>

</uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout>

Now you need to update the “ScrollViewActivity.java” class in your “src” folder.  ScrollViewActivity extends “BaseActivity” and implements “OnRefreshListener“. Update your class according to below coding.

package com.tutecentral.pulltorefreshexample;

import uk.co.senab.actionbarpulltorefresh.library.ActionBarPullToRefresh;
import uk.co.senab.actionbarpulltorefresh.library.PullToRefreshLayout;
import uk.co.senab.actionbarpulltorefresh.library.listeners.OnRefreshListener;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class ScrollViewActivity extends BaseActivity implements OnRefreshListener {

	 private PullToRefreshLayout mPullToRefreshLayout;
	   TextView textView;

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

		textView=(TextView)findViewById(R.id.scrollTextView);

		///You will setup the action bar with pull to refresh layout
		mPullToRefreshLayout = (PullToRefreshLayout) findViewById(R.id.ptr_layout);
		ActionBarPullToRefresh.from(this)
              .allChildrenArePullable()
              .listener(this)
              .setup(mPullToRefreshLayout);

	}

	@Override
	public void onRefreshStarted(View view) {
		// TODO Auto-generated method stub

		/**
		 * Below  AsyncTask class is used to update the view
		 * Asynchronously
		 */
		new AsyncTask<Void, Void, Void>() {

	            @Override
	            protected Void doInBackground(Void... params) {
	                try {
	                    Thread.sleep(5000);
	                    //Here you can get the new text from DB or through a web service
	                    //Then YOu can pass it to onPostExecute() method to
	                    //Update the view

	                } catch (InterruptedException e) {
	                    e.printStackTrace();
	                }
	                return null;
	            }

	            @Override
	            protected void onPostExecute(Void result) {
	                super.onPostExecute(result);

	                //Here you can update the view
	                textView.setText(textView.getText().toString()+"--New Content Added");

	                // Notify PullToRefreshLayout that the refresh has finished
	                mPullToRefreshLayout.setRefreshComplete();
	            }
	        }.execute();
	}

}

Now we can run this application in  emulator or in a real android device to check. Below you can download the sample codes for this program. See the video demonstration of this tutorial to how to follow this tutorial.  I hope this tutorial was helped you. If there is any problems  or suggestions  regarding this article please  comment below. Dont forget to Like our Facebook Page. Subscribe to our website, Google Plus  and Youtube Channel for more tutorials. Thank you for visiting our website.

Video Demonstration

 Downloads

Download the complete project
  • xdarksyndrome

    Hello,

    Thank you for the tutorial. But I have a question. How do I implement this using a Fragment? What do I have to do? Which java classes do I have to modify?

    Please respond.
    Thank you very much.

    • Okay. Fragments can be used in different situations. Can you explain me where do you going to use fragments (Ex: tabs, pages in single activity ect..)? If you need to use this in tab you need to create a class and extend the Fragment and implement the OnRefreshListener then in OnCreateView() method you have to identify the correct fragment then you can update the fragment in onRefreshStarted() method similar to other class in this tutorial. You can find an example in sample application of ActionBar-PullToRefresh Library how to use this with fragments and tabs. You can refer that code. If you have further problems regarding this tutorial feel free to ask. Thank you

  • Ramesh Emandi

    First of all, thanks for elaborate tutorial and the video too. The app is very good illustration too.

    Sorry to say that the approach is NOT WORKING now.
    I think there is a change in SmoothProgressBar library after you have posted this. I see that SmoothProgressBar library is updated 12 days back i.e approximately 28thJan2014. Your method is NOT WORKING when downloading the latest SmoothProgressBar.
    When importing the “main” project is also showing errors. Whereas in your video the main project doesn’t have any errors.
    For now i am managing by using your packaged code, the complete code. Using the main and library from that package and using in my project.
    Do post if you have solution with latest libraries.

    • Ahamed Ishak

      Thank you very much for informing about the issue. I did this tutorial myself using in updated SmoothProgressBar and PullToRefresh Library. But I didn’t get an error in SmoothProgressBar or PullToRefresh Library. Can you tell me waht is the error you got. Is it a runtime error. Can you give me some additional details about error so have an idea about the problem.

  • David Hoxeng

    This is a fantastic article! Would you be close to finishing your article on how to do it with compact?

    • Ahamed Ishak

      Thank you very much.. I’ll do a separate tutorial on PullToRefresh with ActionBarCompact. Subscribe our social media channels so you may not miss any tutorials and videos. 😀

  • Khin Sandar

    Thank ^-* . May I know , I can change API level min 14 to target 15 ? What should I change other library setting ?

    • Ahamed Ishak

      Nothing to change in other libraries.. You can simply use those libraries as same as in this tutorial.

  • Phani Kumar

    This is a nice Article. I have a doubt..
    How can I use Action Bar Sherlock with this project. to implement action bar pull to refresh in Android versions below 11 ?
    Thanks in Advance

  • Arun Badole

    Thanks… very helpful tutorial.

  • i was looking this like a crazy man thanks a lot http://infomundo.org/android

  • Rafat

    Can you make another tutorial for making Pull to refresh compatible with old devices (minSdkVersion of 7) please it will really appreciated

  • Angie

    how can i use action bar pull to refresh with free flow comcast layout?

  • Ramesh

    this tutorial is very good

  • mustafa addam

    This tut is perfect my question is can this library be applied to map also not only a list or web or text?
    Thanks in advance

  • akhil

    thanx a lot ahamed. DO CONTINUE THIS GOOD WORK. it helps thousands of nube like me.

  • vishal suresh

    very nice tutorial..thanks… how to show the smooth progress bar when the webview load initially..

  • matzul

    the tutorial is really good…thanks

  • When I run it it gives me this error:

    Error:Execution failed for task ‘:app:processDebugResources’.

    > Error: more than one library with package name ‘fr.castorflex.android.smoothprogressbar’

    You can temporarily disable this error with android.enforceUniquePackageName=false

    However, this is temporary and will be enforced in 1.0

  • Rishabh

    very nice tutorial for the begineer…

  • Akshay Gangurde

    Hey, used tutorial and its working fab. But the problem is that I’m having One more layout above ListView and when I run the code ListView get overriden on that layout.Please provied me solution to avoide this situation…ASAP

  • Bo Wu

    Thanks, it’s work.

  • Bo Wu

    dear. i have a new question. how to pull-up .it is only pull-down. thank you for all.