Setting PopupMenu menu items programmatically

I have a PopupMenu and I know the usual way to associate a menu to it is to use popup.getMenuInflater().inflate(R.menu.my_menu, popup.getMenu()); or something of the like. My problem is, I have an array of items that I want in the menu and I need to be able to change them programmatically in Java. How can I do this?

83692 次浏览

Just figured it out; for anyone who runs into this same problem you just do:

popup.getMenu().add(groupId, itemId, order, title);

for each MenuItem you want to add.

Just create the popup menu registering the view the popup will show underneath and use the getMenu() method to add the values. Don't forget to call show();

PopupMenu menu = new PopupMenu(this, view);


menu.getMenu().add("titleRes");
menu.show();

Defines ids in popupmenu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">


<item
android:id="@+id/slot1"
app:showAsAction="ifRoom|withText"
android:title="Movies"
android:visible="true"/>
<item
android:id="@+id/slot2"
app:showAsAction="ifRoom|withText"
android:title="Music"
android:visible="true"/>
<item
android:id="@+id/slot3"
app:showAsAction="ifRoom|withText"
android:title="Comedy"
android:visible="true"/>


</menu>

PopupMenu popupMenu = new PopupMenu(FullMenuActivity.this, view);
popupMenu.setOnMenuItemClickListener(FullMenuActivity.this);
popupMenu.getMenu().add(1, R.id.slot1, 1, "slot1");
popupMenu.getMenu().add(1,R.id.slot2,2,"slot2");
popupMenu.getMenu().add(1,R.id.slot3,3,"slot3");
popupMenu.show();

 @Override
public boolean onMenuItemClick(MenuItem item) {


switch (item.getItemId()) {
case R.id.slot1:
SessionManager.selected_slot = item.getTitle().toString();
Toast.makeText(this, "slot1 Clicked", Toast.LENGTH_SHORT).show();
return true;
case R.id.slot2:
SessionManager.selected_slot = item.getTitle().toString();
Toast.makeText(this, "slot2 Clicked", Toast.LENGTH_SHORT).show();
return true;
case R.id.slot3:
SessionManager.selected_slot = item.getTitle().toString();
Toast.makeText(this, "slot3 Clicked", Toast.LENGTH_SHORT).show();
return true;
default:
return true;
}
}

@Voora Tarun gave a good answer, and I based my answer on it: First instead using fake mune.xml resources, I think better approach is to create ids file instead:

ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="menuGroup" type="id"/>
<item name="menu1" type="id"/>
<item name="menu2" type="id"/>
<item name="menu3" type="id"/>
</resources>

Then you can do something like that:

private void showPopup(final View anchor) {
PopupMenu popupMenu = new PopupMenu(anchor.getContext(), anchor);
popupMenu.getMenu().add(R.id.menuGroup, R.id.menu1, Menu.NONE, "slot1");
popupMenu.getMenu().add(R.id.menuGroup, R.id.menu2, Menu.NONE,"slot2");
popupMenu.getMenu().add(R.id.menuGroup, R.id.menu3, Menu.NONE,"slot3");
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(anchor.getContext(), item.getTitle() + "clicked", Toast.LENGTH_SHORT).show();
return true;
}
});
popupMenu.show();
}

Here is a complete solution with IDs set and handled:

        this.findViewById(R.id.hamburger_menu).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu menu = new PopupMenu(getApplicationContext(), v);
menu.getMenu().add(Menu.NONE, 1, 1, "Share");
menu.getMenu().add(Menu.NONE, 2, 2, "Comment");
menu.show();


menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {


int i = item.getItemId();
if (i == 1) {
//handle share
return true;
} else if (i == 2) {
//handle comment
return true;
} else {
return false;
}
}


});
}
});

Note: share and comment are for example, also you can put constants for the numbers 1,2 to make the code more readable.

Also, I put Menu.NONE because I don't care about grouping the menu items. In case you want to make group set group id = 1, 2, etc...

Try this:

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

In java

     private void getPopup(Activity sContext,TextView textView, ArrayList<String> arrayList) {
final PopupMenu popupMenu = new PopupMenu(sContext, textView);
for (int i = 0; i < arrayList.size(); i++) {
popupMenu.getMenu().add(i, Menu.FIRST, i, arrayList.get(i));
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
textView.setText(item.getTitle());
return false;
}
});
popupMenu.show();
}

In Kotlin

private fun getPopup(
sContext: Activity,
textView: TextView,
arrayList: ArrayList<String>
) {
val popupMenu = PopupMenu(sContext, textView)
for (i in 0 until arrayList.size) {
popupMenu.getMenu().add(i, Menu.FIRST, i, arrayList[i])
}
popupMenu.setOnMenuItemClickListener(object :
PopupMenu.OnMenuItemClickListener {
override fun onMenuItemClick(item: MenuItem): Boolean {
textView.setText(item.getTitle())
return false
}
})
popupMenu.show()
}

If you're looking for generated popup items with callbacks, used this.

Java

public static void popupMenu(final Context context, View anchor, final LinkedHashMap<String,IPopupMenu> options){
PopupMenu popupMenu = new PopupMenu(context, anchor);
for(String key : options.keySet()){
popupMenu.getMenu().add(key);
}
popupMenu.getMenuInflater().inflate(R.menu.popup_menu,popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {


options.get(menuItem.getTitle()).onClick();
return true;
}
});


popupMenu.show();
}


public interface IPopupMenu{
void onClick();
}

XML

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">


</menu>


Example

LinkedHashMap<String,IPopupMenu> menu_items = new LinkedHashMap<>();
menu_items.put("Item Name", new Utils.IPopupMenu() {
@Override
public void onClick() {
//do your code
}
});
menu_items.put("My Item", new Utils.IPopupMenu() {
@Override
public void onClick() {
//do code
}
});


//you can anchor the popup menu to whatever you like. i.e Button, TextView, View.
popupMenu(context,button,menu_items);

From String Array Resources

values > strings.xml

<string-array name="MainCategories">
<item>Crop</item>
<item>Animals</item>
<item>Equipment</item>
<item>Other</item>
</string-array>

Java code:

    String []categories=getResources().getStringArray(R.array.MainCategories);
PopupMenu popupMenu=new PopupMenu(MainActivity.this,sortExpenseBtn);


for(String item: categories)
popupMenu.getMenu().add(item);


popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
String selected = item.getTitle();
return true;
}
});
popupMenu.show();