Show popup menu on `ActionBar` item click - android

I have an ActionBar with an action item on it. After clicking on the action item, I want to show a popup menu.
I implemented this method, but I want to anchor it to the action item or to the ActionBar, not to any view from layout. How to get some kind of view to anchor it from MenuItem?
public boolean onOptionsItemSelected(MenuItem item) {
PopupMenu popupMenu = new PopupMenu(this, ??????); // What view goes here?
popupMenu.inflate(R.menu.counters_overflow);
popupMenu.show();
// ...
return true;
}

So finally I found solution. When you want to anchor popupmenu to ActionItem in ActionBar you need to find view that renders ActionItem.
Simple find view with findViewById() where id is same as id of your menu item in xml.
DISPLAYING POPUP:
public boolean onOptionsItemSelected(MenuItem item) {
// ...
View menuItemView = findViewById(R.id.menu_overflow); // SAME ID AS MENU ID
PopupMenu popupMenu = new PopupMenu(this, menuItemView);
popupMenu.inflate(R.menu.counters_overflow);
// ...
popupMenu.show();
// ...
return true;
}
MENU:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
....
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/ic_overflow"
android:showAsAction="ifRoom"
android:title="#string/menu_overflow"/>
....
</menu>
If menu item is not visible (is in overflow) it does not work. findViewById returns null so you have to check for this situation and anchor to another view.

The accepted answer wasn't working for me, so I found the problem by trial and error.
public boolean onOptionsItemSelected(MenuItem item)
{
View menuItemView = findViewById(item.getItemId());
showPopupMenu(menuItemView)
return true;
}
private void showPopupMenu(View anchor)
{
PopupMenu popup = new PopupMenu(this, anchor);
popup.getMenuInflater().inflate(R.menu.my_popup_menu, popup.getMenu());
popup.show();
}
The key here is that, the item in onOptionsItemSelected(MenuItem item) must be shown on ActionBar. If the item is one of the items that appear when you press the 3 vertical dots on top right of ActionBar, then your app will crash.

plz try this ..
#Override
public boolean onOptionsItemSelected(MenuItem item){
String str=item.getTitle().toString();
Toast.makeText(getBaseContext(), str,Toast.LENGTH_LONG). show();
View view=findViewById(item.getItemId());
switch(view.getId()){
case Menu.FIRST:
showPopup(view); // calling method
}
return super.onOptionsItemSelected(item);
}
// custom method
private void showPopup(final View view) {
PopupMenu popupMenu = new PopupMenu(view.getContext(), view);
popupMenu.getMenu().add(0, 0, Menu.NONE, "Item 1");
popupMenu.getMenu().add(0, 1, Menu.NONE, "Item 2");
popupMenu.getMenu().add(0, 2, Menu.NONE, "Item 3");
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(view.getContext(), item.getTitle() + "clicked", Toast.LENGTH_SHORT).show();
return true;
}
});
popupMenu.show();
}

In addition to the Accepted Answer, the issue of re-inflating the popup on each call to onOptionsItemSelected() method can be simplified by doing it only once and just showing it as many times as we want.
(this works even for custom toolbar inflated via Menu Layout Inflater at runtime. Just keep in mind that the findViewById() to get the Menu item's view can return non-null value only when the view is actually present on the screen, ie, should be visible on the toolbar/actionbar.
Note: If the view is preset in the overflow menu of toolbar/actionBar there might be a chance that the view might get inflated only after the overflow menu was invoked at least once - using 3 dots?)
public class SomeActivity{
private PopupMenu popup;
.... // some code of the activity
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int menuItem = item.getItemId();
switch (menuItem) {
case R.id.tb_menu_plus:
View menuItemView = findViewById(R.id.tb_menu_plus);
if(popup == null) {
popup = new PopupMenu(this, menuItemView);
popup.inflate(R.menu.dropdown_popup_menu);
}
popup.show();
return true;
}
return super.onOptionsItemSelected(item);
}

If you don't want the menu to be gone when you click specific item return false on that item.
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId())
{
case R.id.itemShare_:
onShareClicked();
return true; // the menu will be gone
case R.id.itemCopy_:
onCopyClicked();
return true; // the menu will be gone
case R.id.itemSelectAll_:
onSelectAllClicked();
return false; // the menu will stay
// ...
}

public boolean onOptionsItemSelected(MenuItem item) {
final View addView = getLayoutInflater().inflate(R.layout.add, null);
new AlertDialog.Builder(this).setTitle("Add a Word").setView(addView)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addWord((TextView) addView.findViewById(R.id.title));
}
}).setNegativeButton("Cancel", null).show();
return (super.onOptionsItemSelected(item));
}
get full source form here..
http://vimaltuts.com/android-tutorial-for-beginners/android-action-bar-tab-menu-example

Related

How to show the selected item in popup menu which is inside a fragment using a check box?

I am using an image button for a popup menu to popup everything is working fine but when I select an item in the menu the item is selected and it doesn't show the selection so that I could identify the selected item.The checkbox remains unchecked even after the selection
menu_icon_img=myView.findViewById(R.id.Id_customer_over_flow);
menu_icon_img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (getActivity() != null) {
PopupMenu popup = new PopupMenu(getActivity(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.sort_menu_items, popup.getMenu());
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_name_a_z:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
case R.id.select_name_z_a:
if (item.isChecked()) item.setChecked(false);
else item.setChecked(true);
return true;
default:
return false;
}
}
});
}
}
XML
<menu xmlns:android="http://schemas.android.com/apk/res/android"
>
<group
android:checkableBehavior="single"
>
<item
android:id="#+id/select_name_a_z"
android:title="#string/name_a_z"
android:checkable="true"
/>
<item
android:id="#+id/select_name_z_a"
android:title="#string/name_z_a"
android:checkable="true"
/>
</group>
</menu>
The problem is you are creating the popup menu from onClick of an imageview. whenever a click event occures a new instance of popup menu is being created.
to avoid this initiate the popup menu in onCreate method. And call popup.show() from onClick() method.
Toolbar menus are supposed to navigate you the specified activities or fragments on click of the pop up.I am not sure what is the problem , but once you click on any MenuItem it will navigate you to given Intent associated with the the id for example,
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_name_a_z:
Intent intent=new Intent(MainActivity.this,SecondActivity.this);
startActivity(intent);
return true;
If you are using a checkable menu item then change the below code from
case R.id.select_name_z_a:
if (item.isChecked())
item.setChecked(false);
else item.setChecked(true);
return true;
Do like
if (!item.isChecked()) item.setChecked(true);
Because item.ischecked() is false in the beginning state.
Made some changes to your above code, Try this
menu_icon_img=findViewById(R.id.Id_customer_over_flow);
popup = new PopupMenu(getApplicationContext(), menu_icon_img);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.sort_menu_items, popup.getMenu());
menu_icon_img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (this != null) {
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Menu menu = popup.getMenu();
for(int i = 0;i<menu.size();i++){
menu.getItem(i).setChecked(false);
}
item.setChecked(true);
return true;
}
});
}
}
});
Also for all items in menu set:
android:checkable="true"

How to prevent popup menu from closing on checkbox click

I search a lot on net but there is nothing about preventing popup menu from closing.
Whenever i click on checkbox item or any other popup menu item, popup menu dismiss itself. How can i prevent it from dismissing when user check/uncheck checkbox in popup menu.
I'm showing popup menu on actionbar-menu item's click event.
//main_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.worldofjobs.woj.MainActivity" >
<item
android:id="#+id/action_popUpMenu"
android:icon="#drawable/ic_action_overflow"
android:title="#string/main_action_popUpMenu"
app:showAsAction="always"/>
</menu>
//popup_items.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/refresh_item"
android:title="#string/main_refresh"/>
<item
android:id="#+id/checkbox_item"
android:checkable="true"
android:title="Start notification"/>
<item
android:id="#+id/changePasswrod_item"
android:title="#string/main_changePassword"/>
<item
android:id="#+id/deleteAccount_item"
android:title="#string/main_deleteAccount"/>
<item
android:id="#+id/logout_item"
android:title="#string/main_logout"/>
</menu>
/**
* Shows popup menu on click of action bar-menu inflates from
* menu.pop_items-xml
*/
private void showPopup() {
try {
View v = findViewById(R.id.action_popUpMenu);
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(MainActivity.this);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(R.menu.pop_items, popup.getMenu());
popup.show();
} catch (Exception e) {
Log.e("MainActivity-showPopup:", e.toString());
}
}
/**
* Handles click events of popup menu items
*/
#Override
public boolean onMenuItemClick(MenuItem item) {
super.onMenuItemSelected(1, item);
switch (item.getItemId()) {
case R.id.refresh_item:
refresh();
return true;
case R.id.checkbox_item:
return true;
case R.id.changePasswrod_item:
changePasswordPopup();
return true;
case R.id.deleteAccount_item:
deleteAccount();
return true;
case R.id.logout_item:
session.logout();
finish();
return true;
}
return true;
}
Using popupMenu.show() to immediately re-show the popup menu does not work correctly with checkable menu items when changing their checked states.
Here a method that prevents closing the popup menu in the first place. Make sure that onMenuItemClick returns false.
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
item.setChecked(!item.isChecked());
// Do other stuff
// Keep the popup menu open
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item.setActionView(new View(context));
item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false;
}
});
return false;
}
});
The trick here is to show the menu right after it dismisses.
Below is a sample code snippet:
popupMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
if(item.getItemId()==R.id.search_by_date_checkbox){
item.setChecked(!item.isChecked());
}
//This is the trick here!!!!
popupMenu.show();
return true;
}
});
You can try this trick with your code! This is how I did it. :)
Oliver's answer above (https://stackoverflow.com/a/31727213/2423194) gave me a crash, and its message told me to use MenuItemCompat instead. After some tweaking to this code, it works:
// Keep the popup menu open
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
item.setActionView(new View(getContext()));
MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
#Override
public boolean onMenuItemActionExpand(MenuItem item) {
return false;
}
#Override
public boolean onMenuItemActionCollapse(MenuItem item) {
return false;
}
});
Thanks Oliver!
Try declaring the PopupMenu globally and calling popup.show(); before returning true in onMenuItemClick function.
Got it working by adding popup.show(); on the click of the button and at the end of the click.
final ImageButton layerButton = (ImageButton) findViewById(R.id.layers);
final PopupMenu popup = new PopupMenu(MapsActivity.this, layerButton);
popup.getMenuInflater().inflate(R.menu.toolbar_menu, popup.getMenu());
layerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Here
popup.show();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
handleClicksOnCheckBoxes(item);
return true;
}
});
//And here
popup.show();
}
});
However, this is not an optimal solution because if the list has so many items that it will be possible to scroll the list, the list will be scrolled to the top when clicking on an item.
In your case R.id.checkbox_item
return false;
This will tell the system that the event has not yet been handeled and it will not dimiss the menu. See HERE

How to get listitem id when I click on PopUp menu item?

In my application I have attached popup menu with each item in listview. The popup menu has further two items when we click on popup menu icon.I have implemented OnMenuItemClickListener in my activity to listen for popup menu item clicks which is working fine.But the problem is that How do I get to know the listitem id (not popup menu item id) when I click on popup menu icon for any listview item.The popup menu code is below:
public void showPopup(View v) {
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.actions);
popup.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_play:
return true;
default:
return false;
}
}
Please tell me what is "listitem id" that you want to know? I doubt that it's a "listitem view's id". Probably you're thinking about "position", right?
I don't know where do you call showPopup(View v) from, but you also need to pass the position there:
public void showPopup(View v, int listItemPosition) {
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.actions);
popup.show();
}
Your goal is to know this position in the onMenuItemClick(MenuItem item) callback.
The simplest way to achieve this is to create variable "listItemPositionForPopupMenu", store this position there and read it in the onMenuItemClick callback:
private int listItemPositionForPopupMenu;
public void showPopup(View v, int listItemPosition) {
listItemPositionForPopupMenu = listItemPosition;
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.actions);
popup.show();
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_play:
// read the listItemPositionForPopupMenu here
return true;
default:
return false;
}
}
You can also do it in many other ways, like creating you own OnMenuItemClickListener listener with listItemPosition variable in constructor and create custom interface with onMenuItemClick(MenuItem item, int listItemPosition). Or you can just create an anonymous class, then you don't need to have the listItemPositionForPopupMenu member variable:
public void showPopup(View v, final int listItemPosition) {
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_play:
// read the listItemPosition here
return true;
default:
return false;
}
}
});
popup.inflate(R.menu.actions);
popup.show();
}

Popup menu android

I want to make a popup menu that comes from the action bar. So instead of the icon in the action bar there would be something that says menu, and then when clicked it will trigger this popup. Is this possible?
private void showPopupMenu(View v){
popupMenu= new PopupMenu(menuActivity.this, v);
popupMenu.getMenuInflater().inflate(R.menu.action_menu, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
return true;
}
});
popupMenu.show();
}
Try
QuickAction3D
and just specify the menu button as the anchor

Why opens popupmenu inside action bar

I am working on an timetable app, but I have a strange problem, I created a popupmenu that opens upon clicking an action-bar item.
The popup works, but it opens inside the action bar, I want that it opens in the view below.
My code..
#Override
public void onCreateOptionsMenu(
Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.lists_choice_mode_mulitplue, menu);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.inverse:
showPopupMenu(this.getView());
return true;
}
return false;
}
private void showPopupMenu(View v){
final Activity activity = getSupportActivity();
PopupMenu popupMenu = new PopupMenu(activity, v);
popupMenu.getMenuInflater().inflate(R.menu.popup, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(activity,
item.toString(),
Toast.LENGTH_LONG).show();
return true;
}
});
popupMenu.show();
}
My .xml layout files
popup.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="#+id/group_popupmenu">
<item android:id="#+id/menu1"
android:title="Popup menu item 1"/>
<item android:id="#+id/menu2"
android:title="Popup menu item 2"/>
<item android:id="#+id/menu3"
android:title="Popup menu item 3"/>
</group>
</menu>
My action bar button .xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/inverse"
android:showAsAction="always|withText"
android:title="Week"
android:titleCondensed="Week" />
</menu>
Yeah it's fixed now!
Its wrong to to showPopupMenu(this.getView());
It should be the id of icon in action bar.. as following..
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.inverse:
showPopupMenu(R.id.inverse);
return true;
}
return false;
}
change showpopupmenu(view v) in
private void showPopupMenu(int id){
final Activity activity = getSupportActivity();
View v = activity.findViewById(id);
PopupMenu popupMenu = new PopupMenu(activity, v);
popupMenu.getMenuInflater().inflate(R.menu.popup, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(activity,
item.toString(),
Toast.LENGTH_LONG).show();
return true;
}
});
popupMenu.show();
}
It works now! Thanks for the answers it didn't help me but it is appreciated!
You are inflating your menu layout, and I think that you want to inflate your activity layout.
check this previous question that shows how to inflate a layout:
How to inflate one view with a layout

Categories

Resources