Changing view on Menu Item in Action Bar

The Holo Dev picture The Holo Dev · Mar 30, 2012 · Viewed 19.1k times · Source

I'm attempting to implement a refresh button in my app to allow a user to manually re-sync to a web server. The code works, but I'm having trouble figuring out the action views (at least, I think that's what I'm supposed to be using).

My menu item is here:

<item
    android:id="@+id/main_menu_refresh"
    android:enabled="true"
    android:icon="@drawable/refresh"
    android:orderInCategory="1"
    android:showAsAction="ifRoom"
    android:title="@string/refresh" 
    android:actionViewClass="android.widget.ProgressBar">
</item>

The problem is, it always shows the ProgressBar. I wondered if it worked like the search widget (the only example I really see online) and added the collapseActionView tag to the showAsAction and that prevented it from showing up immediately. However, when I click the refresh button, the icon disappears (good), but so does the Title in the action bar, and the ProgressBar appears on the left side of the window where the title used to be. Also not what I wanted.

As something of a last ditch effort, I attempted to add this to my code, and remove the actionViewClass from the XML:

MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
Log.w("MyApp", "Have Menu");
ProgressBar pb = new ProgressBar(ReadingList.this);
refresh.setActionView(pb);

That didn't work either, giving me a null pointer error on setActionView.

I need a solution that I can call from any function (there is an auto-sync period at the beginning I would like the ProgressBar to display during as well), and be able to return it to it's static icon after.

I tried reading through this question, but I am having trouble understanding what the answer means. I feel like I was trying to do just what it says, but I guess not. Any assistance is much appreciated.

Edit: For sastraxi's suggestion.

public class IconSwitcher extends LinearLayout{



public IconSwitcher(Context context) {
    super(context);

    ProgressBar pb = new ProgressBar(context);
    ImageView iv = new ImageView(context);

    addView(iv);
    addView(pb);
}
}

This is my class thus far. However, when I try and reference it with:

MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
IconSwitcher ic = (IconSwitcher) refresh.getActionView();

I get a null pointer error. on creating the IconSwitcher. The button XML is as follows:

<item
    android:id="@+id/main_menu_refresh"
    android:enabled="true"
    android:icon="@drawable/refresh"
    android:orderInCategory="1"
    android:showAsAction="ifRoom"
    android:title="@string/refresh" 
    android:actionViewClass="IconSwitcher">
</item>

I'm just having a difficult time on referencing that IconSwitcher View.

Edit 2: I'm appearantly having trouble referencing the Menu Item at all.

MenuItem refresh = (MenuItem)findViewById(R.id.main_menu_refresh);
refresh.setVisible(false);

Also gives me a null pointer when I try and set the visibility. What is wrong with my references?

Answer

sastraxi picture sastraxi · Mar 30, 2012

Instead of setting your action view class to a ProgressBar, set it to a custom LinearLayout class, as such:

class MyViewItem extends LinearLayout

Add a ProgressBar and an ImageView as children in its constructor with addView, and set these childrens' visibilities as either GONE or VISIBLE when your code requires it.