63

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));
}
Johnathan Au
  • 5,244
  • 18
  • 70
  • 128

6 Answers6

110

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.

David Manpearl
  • 12,362
  • 8
  • 55
  • 72
  • Hi thanks. Can you provide an example that would display the logout if user is logged in? Which method would I add this logic? Also, I don't understand the variables MENU_ADD...etc – Johnathan Au Mar 22 '13 at 22:37
  • Done. See updated answer above. The menuId values are required so that you can know which menu item was pressed by the user when processing the menu activity in onOptionsItemSelected(). – David Manpearl Mar 22 '13 at 22:51
  • Alright nice. Few more questions. The onPrepareOptionsMenu method, would I have to recreate every other item, or is that logic you added in their enough? The MENU_LOGOUT variable, would that not be +3 as opposed to +4, because it would replace MENU_LOGIN when it becomes visible? – Johnathan Au Mar 22 '13 at 22:55
  • You must recreate the if() logic for each item every item. In onPrepareOptionsMenu() you must place logic to decide if the menu item should be displayed. As a good practice, you should also recreate the same logic in onOptionsItemSelected(). This is just in case things change during the potentially long interval between the time when the user first presses the menu button and when he finally presses the specific menu item button (i.e. how much time does he leave the menu displayed before selecting an item). Don't forget to upvote (triangle) and accept (check) correct answers. – David Manpearl Mar 22 '13 at 22:59
  • 1
    The item id values (i.e. MENU_LOGOUT) do not have to be sequential. They can be any number. You can have as many as you want. Just don't duplicate any values. Only display the ones you need at any one time. Therefore, it is ok to have one of those for every possible menu label, even if some are very rarely displayed. – David Manpearl Mar 22 '13 at 23:03
  • I have a doubt...suppose I am getting 5 menu options from backend as of now(getting it from backend because any time I may add another menu option), so will the app keep on fetching the menu from backend every time for every view? Any ideal way to do it? – Abhinav Feb 13 '18 at 13:47
  • .setShowAsAction(1); this allow you to show as Always – Monzur Aug 05 '21 at 05:40
8

In my case the menu items are in the ArrayList , - try this Hope it will help u :)

public void onClick(View v)
{
    PopupMenu menu = new PopupMenu(DialogCheckBox.this, v);
    for (String s : limits) { // "limits" its an arraylist  
        menu.getMenu().add(s);
    }
    menu.show();
}
Agilanbu
  • 2,747
  • 2
  • 28
  • 33
7

you can call invalidateOptionsMenu() (note:need to use compatability library like actionBarSherlock to access in case you need to support low API versions) , and then update the menu items according to the status.

there you could hide the login action item and show the logout action item.

you might also try update the icon itself but i never tried it.

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • 1
    nice additional touch. That's necessary to replace LOGIN with LOGOUT icons like @johnathan-au asked because it'll cause `onPrepareOptionsMenu()` to be called again – Someone Somewhere Jan 18 '17 at 19:18
1
private void getPopup(final TextView textView, ArrayList<String> arrayList) {
        final PopupMenu popupMenu = new PopupMenu(sContext, textView);
        for (int i = 0; i < arrayList.size(); i++) {
            popupMenu.getMenu().add(arrayList.get(i));
        }
        popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                textView.setText(item.getTitle());
                return false;
            }
        });
        popupMenu.show();
    }
Safal Bhatia
  • 245
  • 2
  • 6
  • If your data come from Apis and you show data in Popup then this code help you. Also this is used for dynamic popup. – Safal Bhatia Sep 17 '19 at 10:22
0

Simple way to create menu items :

Dynamic_PopUpMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PopupMenu menu = new PopupMenu(DialogCheckBox.this, v);
                menu.getMenu().add("AGIL"); // menus items 
                menu.getMenu().add("AGILANBU"); // menus items
                menu.getMenu().add("AGILarasan");
                menu.getMenu().add("Arasan");
                menu.show();
            }
        });

Try this :)

Agilanbu
  • 2,747
  • 2
  • 28
  • 33
0

it's so easy

To create the menu

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    for (int i = 0; i < list.size(); i++) {
        menu.add(0, i, 0, "Menu Name").setShortcut('5', 'c');
    }

    return true;
}

to get the details from clicked menu

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId(); //to get the selected menu id
    String name = item.getTitle(); //to get the selected menu name

    return super.onOptionsItemSelected(item);
}