Get context of PopupMenu like ContextMenu
So my ExpandableListView
has group rows that are defined like :
group_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/GroupName"
style="@style/ListViewRowStyle"
android:paddingLeft="40dp"
android:textSize="18sp" >
</TextView>
<ImageView
android:id="@+id/Menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:contentDescription="@string/default_content_description_text"
android:src="@drawable/ic_menu_moreoverflow_normal_holo_light" >
</ImageView>
</RelativeLayout>
When you click on the TextView
it will expand or collapse depending on whether or not the child rows are currently displayed. I have attached an OnClickListener
to the ImageView
in the group row. When this ImageView
is clicked I launch a PopupMenu
like the images below :
Once the PopupMenu
is displayed and one of the actions is clicked, I would like to perform an action on all children of the group. The problem is that I cannot determine the row in which the ImageView
was clicked.
The only way I have figured out how to apply an action to all children is with a ContextMenu
like the image below :
I want to avoid using a ContextMenu
because a LongClick on a group row may not be obvious for a user to figure out that it would bring up some actions to perform on the children rows. I think the more obvious design is to anchor a PopupMenu
to an ImageView
(in my case a menu icon) and have the action be applied to the children rows of that group. How can I get this functionality with a PopupMenu
?
So I figured out that in order to have some context of which menu icon was clicked, I utilized the setTag() and getTag() methods of the View
class and just applied these methods to the ImageView
(menu icon).
You need:
- A
View
where to inflate the PopUpMenu (yourImageView
) - A
PopUpMenu
saved in res/menu, in this casepopup_select_deselect.xml
- Your own
onMenuItemClickListener
declared as internal class, in this caseonMenuItemClickListener_View
Code:
//TODO initialize rows[]
for (int i = 0; i < rows.lenght; i++){
//inflate you group_row
getLayoutInflater().inflate(R.layout.group_row, (ViewGroup)findViewById(R.id.rows_container));
ImageView v_Overflow = (ImageView)findViewById(R.id.Menu);
//Set onClickListener
v_Overflow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
View v_Button = v;
PopupMenu pum= new PopupMenu(YourActivity.this, v);
//set my own listener giving the View that activates the event onClick (i.e. YOUR ImageView)
pum.setOnMenuItemClickListener(new onMenuItemClickListener_View(v) );
//inflate your PopUpMenu
getMenuInflater().inflate(R.menu.popup_select_deselect, pum.getMenu());
pum.show();
}
});
//Update the id of your TextView
.setId(i); //the i value will be your UNIQUE id for the ImageView
}
The code above is only a static declaration of what your own OnMenuItemClickListener
will do.
Pay attention to the given View
in the constructor of the following listener. When you create an instance of this listener, the View
Id is the same declared in the XML layout. At runtime it will be updated, so when the method onMenuItemClick
will be called, the TextView
ID is already changed.
Here's the code:
private class onMenuItemClickListener_View implements OnMenuItemClickListener{
View v_View;
public onMenuItemClickListener_View(View v){
v_View=v;
}
@Override
public boolean onMenuItemClick(MenuItem item) {
int i = v_View.getId();
switch (item.getItemId()) {
case R.id.popupItemSelectAll:
Toast.makeText(YourActivity.this, "Popup Select All for View #: " + rows[i], Toast.LENGTH_SHORT).show();
//TODO your code to select all
return true;
case R.id.popupItemDeselectAll:
Toast.makeText(YourActivity.this, "Popup Deselect All for View #: " + rows[i], Toast.LENGTH_SHORT).show();
//TODO your code to deselect all
return true;
default:
return false;
}
}
}
}