A Better ‘More’ Menu Option For Android Menus

The classic menu in Android apps may be deprecated, but I still use them and develop apps that support them.  The fact is there are an awful lot of devices out there that are using Honeycomb, Gingerbread, Froyo, and the like.  I, for one, have always been a proponent for backwards compatibility.

My biggest complaint with the classic menu, however, has got to be the horrible way we are presented with the buttons when there are any more than 6 options.  Button #6 is replaced with a “More” button, which when clicked replaces the menu with a hideous, non-styled, vertical text-only menu:

Classic Android Menu

Classic Android Menu

Classic Android Menu Expanded

Classic Android Menu Expanded

I don’t know about you, but I prefer consistency in a user interface; I want all menus to behave the same, to look the same, and so forth.  And what about the menu icons that you as a developer spent so much time lovingly crafting but Android has decided the user has no use for?

Fortunately Android provides us with the ability to modify the menu as we wish.  Note that it cannot be changed while it is displayed, so I had to come up with a few little tricks to close the menu and reopen it…but this method has been proven and is being used in one of my publicly available apps Zombie Watchdog Veteran.


The first step of course is to create your ‘more’ button.  It’s done just like any other menu button; make your icon and add the button to the menu’s XML file (assuming you are using an XML file and inflating the menu…that’s how I generally do my menus.  This one starts with only three options: Settings, Exit, and More.

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/settingsb"
 android:title="Settings"
 android:icon="@drawable/ic_menu_settings" />
<item android:id="@+id/exitb"
 android:title="Exit"
 android:icon="@drawable/ic_menu_exit" />
<item android:id="@+id/moreb"
 android:title="More..."
 android:icon="@drawable/ic_menu_more" />
</menu>
Better Android Menu

Better Android Menu

Now, in the activity class where the menu is going to be used, we have to create the menu listener.  This is pretty simple, it just listens for when any of the three menu buttons are pressed and acts upon them accordingly.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
 switch (item.getItemId()) {
 case R.id.settingsb:
 Intent sintent = new Intent(this, PrefsActivity.class);
 startActivity(sintent);
 break;
 case R.id.moreb:
 break;
 case R.id.exitb:
 finish();
 break;
 }
 return true;
}

Oh, and I forgot to mention that I created a reference to the menu that we can grab from anywhere inside this activity class. First I defined a member variable Menu mmenu, then when originally inflating the menu, I set that variable to the reference of the menu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
 MenuInflater inflater = getMenuInflater();
 inflater.inflate(R.menu.menu, menu);
 mmenu = menu;
 return true;
}

So now anytime we want to reference the menu, we simply call the variable “mmenu.”

You will probably notice that we don’t have anything happening under the moreb button though.  What we want to have happen of course is to replace the current small menu with a new bigger one. So let’s write a function that does that.

public void expandMenu(){
}

Remember I said we can’t change the menu while it is displayed, so the first thing we are going to do is close the menu.  Then we will completely empty it, deleting all of the options that are currently in it so we can build it again from scratch without anything getting in the way.

public void expandMenu(){
mmenu.close();
mmenu.clear();

We now have a clean and pristine menu, that is just waiting to be populated with our new buttons. Note that the original menu limitation does apply here; if we add more than 6 options Android will take over and add it’s own ‘more’ button again.

mmenu.add(0, R.id.demob, 1, getString(R.string.demo_mode_name)).setIcon(R.drawable.ic_menu_demo);
mmenu.add(0, R.id.newsb, 2, getString(R.string.news)).setIcon(R.drawable.ic_menu_news);
mmenu.add(0, R.id.tipsb, 3, getString(R.string.survival_tips)).setIcon(R.drawable.ic_menu_tips);
mmenu.add(0, R.id.aboutb, 4, getString(R.string.about_page)).setIcon(R.drawable.about_zwd);
mmenu.add(0, R.id.settingsb, 5, getString(R.string.settings_name)).setIcon(R.drawable.ic_menu_settings);
mmenu.add(0, R.id.exitb, 6, getString(R.string.exit)).setIcon(R.drawable.ic_menu_exit);

This is where things get a little tricky.  It seems that Android won’t open the menu again immediately after it has been forced close.  This caused me to pull a lot of hair out before I figured out what was going on….but once I sorted it out, it was a simple matter to resolve.  Really we just implement a little time delay before opening the new menu.  I settled on 500 milliseconds which seems to be short enough that it isn’t noticeable to the average human and long enough that Android doesn’t freak out. In order to delay the opening, I had to create a separate function that is called at the tail end of the expandMenu() function.

public void openIt(){
 new Handler().postDelayed(new Runnable() {
 public void run() {
 openOptionsMenu();
 }
 }, 500);
}

Altogether, this is the expandMenu() function:

public void expandMenu(){
mmenu.close();
mmenu.clear();
mmenu.add(0, R.id.demob, 1, getString(R.string.demo_mode_name)).setIcon(R.drawable.ic_menu_demo);
mmenu.add(0, R.id.newsb, 2, getString(R.string.news)).setIcon(R.drawable.ic_menu_news);
mmenu.add(0, R.id.tipsb, 3, getString(R.string.survival_tips)).setIcon(R.drawable.ic_menu_tips);
mmenu.add(0, R.id.aboutb, 4, getString(R.string.about_page)).setIcon(R.drawable.about_zwd);
mmenu.add(0, R.id.settingsb, 5, getString(R.string.settings_name)).setIcon(R.drawable.ic_menu_settings);
mmenu.add(0, R.id.exitb, 6, getString(R.string.exit)).setIcon(R.drawable.ic_menu_exit);
openIt();

One final thing is to call expandMenu() when the ‘more’ button is pressed.

case R.id.moreb:
 expandMenu();
 break;

We have now successfully replaced the default menu with a bigger and better menu…but one that won’t do anything!  Read on to the next page to resolve that little issue.

Cody (17 Posts)