How can I dynamically create menu items?

Johnathan Au picture Johnathan Au · Mar 22, 2013 · Viewed 66k times · Source

I'm building an Android application and I'm trying to build a user management system where users can login, logout, etc. I want to display a login menu item if the user is logged out and a logout button if the user is logged in. How can I do this dynamically?

This is the layout file right now:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/add" android:title="Add" android:icon="@drawable/ic_menu_add"/>
  <item android:id="@+id/list" android:title="List" android:icon="@drawable/ic_menu_list"/>
  <item android:id="@+id/refresh" android:title="Refresh" android:icon="@drawable/ic_menu_refresh"/>
  <item android:id="@+id/login" android:title="Login" android:icon="@drawable/ic_menu_login"/>
</menu>

This is my Java right now:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    new MenuInflater(this).inflate(R.menu.activity_main, menu);
    return(super.onCreateOptionsMenu(menu));
}

@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
    System.out.println(item.getItemId()==R.id.add);
    if (item.getItemId()==R.id.add)
    {
        //Cannot add spot unless we have obtained the users current location. 
        if((currentLat != 0) && (currentLng != 0))
        {

            System.out.println("loggedin? : "  + auth.isLoggedIn());
            if(!auth.isLoggedIn())
            {
                Toast.makeText(MainActivity.this, "You must be logged in to add a new spot",
                        Toast.LENGTH_LONG).show();
            }
            else
            {


                Intent addIntent = new Intent(MainActivity.this, AddSpot.class);
                Bundle b = new Bundle();
                b.putDouble("currentLat", currentLat);
                b.putDouble("currentLng", currentLng);
                addIntent.putExtras(b);
                startActivity(addIntent);
                return(true);
            }
        }
    }   
    else if(item.getItemId()==R.id.list)
    {
        //Pointless showing them a blank screen if nothing is retrieved from the server
        if(list != null)
        {
            Intent listIntent = new Intent(MainActivity.this, ListLocations.class);
            listIntent.putExtra("list", list);
            startActivity(listIntent);
            return(true);
        }
    }

    if(item.getItemId()==R.id.refresh)
    {
        finish();
        startActivity(getIntent());
        return(true);       
    }

    if(item.getItemId()==R.id.login)
    {
        Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(loginIntent);
        return(true);   
    }

    return(super.onOptionsItemSelected(item));
}

Answer

David Manpearl picture David Manpearl · Mar 22, 2013

How to Dynamically Add Menu Items to an Android Activity

public class yourActivity extends Activity {
    ...
    private static final int MENU_ADD = Menu.FIRST;
    private static final int MENU_LIST = MENU.FIRST + 1;
    private static final int MENU_REFRESH = MENU.FIRST + 2;
    private static final int MENU_LOGIN = MENU.FIRST + 3;

    /**
     * Use if your menu is static (i.e. unchanging)
     */
    /*
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, MENU_ADD, Menu.NONE, R.string.your-add-text).setIcon(R.drawable.your-add-icon);
        menu.add(0, MENU_LIST, Menu.NONE, R.string.your-list-text).setIcon(R.drawable.your-list-icon);
        menu.add(0, MENU_REFRESH, Menu.NONE, R.string.your-refresh-text).setIcon(R.drawable.your-refresh-icon);
        menu.add(0, MENU_LOGIN, Menu.NONE, R.string.your-login-text).setIcon(R.drawable.your-login-icon);
        return true;
    }
    */

    /**
     * Gets called every time the user presses the menu button.
     * Use if your menu is dynamic.
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menu.clear();
        if(enableAdd)
            menu.add(0, MENU_ADD, Menu.NONE, R.string.your-add-text).setIcon(R.drawable.your-add-icon);
        if(enableList)
            menu.add(0, MENU_LIST, Menu.NONE, R.string.your-list-text).setIcon(R.drawable.your-list-icon);
        if(enableRefresh)
            menu.add(0, MENU_REFRESH, Menu.NONE, R.string.your-refresh-text).setIcon(R.drawable.your-refresh-icon);
        if(enableLogin)
            menu.add(0, MENU_LOGIN, Menu.NONE, R.string.your-login-text).setIcon(R.drawable.your-login-icon);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);

        switch (item.getItemId()) {
        case MENU_ADD: doAddStuff(); break;
        case MENU_LIST: doListStuff(); break;
        case MENU_REFRESH: doRefreshStuff(); break;
        case MENU_LOGIN: doLoginStuff(); break;
        }
        return false;
    }

The following specific example adds a MENU_LOGOUT option if the user is logged in.

    private static final int MENU_LOGOUT = MENU.FIRST + 4;

    public boolean onPrepareOptionsMenu(Menu menu) {
        ...
        if(auth.isLoggedIn()) {
            menu.add(0, MENU_LOGOUT, Menu.NONE, R.string.your-logout-text).setIcon(R.drawable.your-logout-icon);
        }
        ...
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        ...
        case MENU_LOGOUT:
            if(auth.isLoggedIn()) {
                doLogout();
            } else {
                Toast.makeText(this, "You must have somehow been logged out between the time the menu button was pressed and now.", Toast.DURATION_LONG).show();
            }
            break;
        ...
    }

That's all there is to it.