Android : Refresh item inside action bar using circular ProgressBar

This android tutorial is about adding a refresh item in the action bar. When refreshing is disabled, a simple image is shown. When refreshing is running, a circular progressbar is shown. Let’s see the screenshots below to show the results.



Test before
If you wish to test before, you can install the application with the following link (Airport AsyncTask on the main screen). The whole source code of the project is also available on github.

logo-app
Your app idea
Michenux
Free   
pulsante-google-play-store
pulsante-appbrain
qrcode-app

Tutorial

1) First, let’s create the xml to describe the menu of the action bar. Create a file into directory res/menu with the following content. In my example, the filename is airport_menu.xml. The menu contains an item airport_menuRefresh, it uses icon ic_menu_refresh, and will always be placed in the action bar.

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:id="@+id/airport_menuRefresh"
         android:icon="@drawable/ic_menu_refresh"
         android:title="@string/menuitem_refresh"
         android:alphabeticShortcut="r"
         android:orderInCategory="1"
         android:showAsAction="always" />
</menu>

2) Then, create the layout that contains the progressbar. This layout is used when refresh is running. Just create a file named actionbar_indeterminate_progress.xml inside folder res/layout with the following content :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_height="wrap_content"
   android:layout_width="56dp"
   android:minWidth="56dp">
    <ProgressBar android:layout_width="32dp"
       android:layout_height="32dp"
       android:layout_gravity="center"/>
</FrameLayout>

3) In your activity, add an instance attribute to preserve a link to the Menu :

private Menu optionsMenu;

4) In your activity, override the methode onCreateOptionsMenu so you can inflate the menu :

public boolean onCreateOptionsMenu(Menu menu) {
    this.optionsMenu = menu;
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.airport_menu, menu);
    return super.onCreateOptionsMenu(menu);
}

5) Override method onOptionsItemSelected to handle the click on the refresh item

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.airport_menuRefresh:

        // Complete with your code
    return true;
    }
    return super.onOptionsItemSelected(item);
}

6) In your activity, add this method that will allow you enable/disable the circular progressbar :

public void setRefreshActionButtonState(final boolean refreshing) {
    if (optionsMenu != null) {
        final MenuItem refreshItem = optionsMenu
            .findItem(R.id.airport_menuRefresh);
        if (refreshItem != null) {
            if (refreshing) {
                refreshItem.setActionView(R.layout.actionbar_indeterminate_progress);
            } else {
                refreshItem.setActionView(null);
            }
        }
    }
}

7) Finally, add calls to setRefreshActionButtonstate(true) and setRefreshActionButtonstate(false). This depends on your application. To see a complete example, download on github the source code of the whole project : the interesting class is AirportActivity.

Share Button

Comments

11 Responses to “Android : Refresh item inside action bar using circular ProgressBar”

  1. Harshitha on June 23rd, 2013 8:38 pm

    Great post…. I cant tell you how thankful i am for this

  2. LasseB on June 28th, 2013 10:18 am

    Thank you!! This helped me so much! :)

  3. Federico on August 22nd, 2013 10:46 am

    Hi Michenux,

    this post is GREAT! I implemented this in my project, but I have a question: how can I show the progress bar on activity start, not only when the action bar’s button is pressed?

  4. Peter on November 11th, 2013 10:10 am

    Hello Laurent,

    great article. I would like to ask for advice. I tried to applied above code to my scenario with FragmentActivity and AsyncTaskLoader where I need to fetch JSON. However when I call setRefreshActionButtonState(true) before I start loader (I start loader onResume of activity) optionMenu is still null therefore refresh is not switched with indeterminate progress bar. Any suggestions how to fix this?

  5. Szymon on November 11th, 2013 6:36 pm

    Great tutorial, many thanks :)

  6. Michenux on November 16th, 2013 2:38 pm

    Maybe you can look at my application “Your App Idea” on github : https://github.com/Michenux/YourAppIdea
    It contains a full and working example in the Airport Fragment. I didnot use an AsyncTaskLoader but the volley library.

  7. John Pirie on January 1st, 2014 5:29 pm

    Woohoo! Finally, a working solution! Thank you. The FrameLayout XML was the key for me.

  8. Javi on January 31st, 2014 12:42 pm

    Hello.

    I followed this tutorial and now i have the progressbar on my actionbar showing more or less as expected. Small problem is, it doesnt animate. Shows up when i click on it (onoptionsitemselected) and when my service finishes, sends a message back to the activity to show the icon again. So the time the progressbar is visible, doesnt animate.

    What am i doing wrong?

    Thanks in advance for your help.

  9. Javi on January 31st, 2014 1:47 pm

    Fixed. Forget about it!

    Thanks alot again!!

  10. Maxrunner on February 11th, 2014 11:57 am

    Hi! how do you deal with configuration changes?

  11. stephen byrne on February 28th, 2014 1:29 pm

    if you are trying to get this to work below api 11
    then step six need to be altered to

    public void setRefreshActionButtonState(final boolean refreshing) {
    if (optionsMenu != null) {
    final MenuItem refreshItem = optionsMenu
    .findItem(R.id.airport_menuRefresh);
    if (refreshItem != null) {
    if (refreshing) {
    MenuItemCompat.setActionView(refreshItem, R.layout.actionbar_indeterminate_progress);
    } else {
    MenuItemCompat.setActionView(refreshItem, null);
    }
    }
    }
    }

Leave a Reply