Android: Context menu example (on long press, gridview)
I received several requests regarding how I created a context menu (the menu activated on a long press) using a gridview and how to call functions such as saving a sound file from this. So I have created a quick example to explain this:
Tutorial
To implement a context menu (long press menu) you first need to include the following imports:
import android.view.ContextMenu; import android.view.View; import android.view.ContextMenu.ContextMenuInfo;
We start a very simple project, with the layout having a single button named button_example:
We then use registerForContextMenu in the onCreate of the activity to tell android that we want this view to create a menu when it is long pressed. This is not limited to buttons, this will work for other views too. You must register each view that you want to have associated with the context menu.
Button btn = (Button) findViewById(R.id.button_example); registerForContextMenu(btn);
You then need to override the onCreateContextMenu method to create the menu:
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context Menu");
menu.add(0, v.getId(), 0, "Action 1");
menu.add(0, v.getId(), 0, "Action 2");
}
And override onContextItemSelected to preform the action when an option is selected from this menu:
@Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Action 1"){function1(item.getItemId());}
else if(item.getTitle()=="Action 2"){function2(item.getItemId());}
else {return false;}
return true;
}
function1 and function2 are just place-holders at the moment that toast a message when they are used. In the above example we are choosing between Action 1 and Action 2 which define which function will be run when an item is selected. We have passed the ID of the view through the context menu and into this function so we can tell what the user was pressing when the context menu was created.
Examples
If you create a gridview and give each item a unique ID then you can use this method to preform actions based on each item. This is the method I use for my soundboard applications to save the sounds to the SD card as a notification or ringtone:
Source
Below is the source code:
package com.contextmenu.test;
import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.Button;
import android.widget.Toast;
public class test extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button) findViewById(R.id.button_example);
registerForContextMenu(btn);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Context Menu");
menu.add(0, v.getId(), 0, "Action 1");
menu.add(0, v.getId(), 0, "Action 2");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle()=="Action 1"){function1(item.getItemId());}
else if(item.getTitle()=="Action 2"){function2(item.getItemId());}
else {return false;}
return true;
}
public void function1(int id){
Toast.makeText(this, "function 1 called", Toast.LENGTH_SHORT).show();
}
public void function2(int id){
Toast.makeText(this, "function 2 called", Toast.LENGTH_SHORT).show();
}
}







Excellent tutorial, the only problem I’m having is that the filename never gets picked up at anypoint, I’m using
yourmove.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (FilmSound.isPlaying())
{
FilmSound.stop();
FilmSound.reset();
FilmSound = MediaPlayer.create(getApplicationContext(), R.raw.yourmove);
FilmSound.start();
}
else {FilmSound = MediaPlayer.create(getApplicationContext(), R.raw.yourmove);
FilmSound.start(); }
}
}
);
as the code for playing the sound file, is there a way of incorporating the context menu and my code.
I’m afraid you haven’t given enough information to explain what problem your having. Also your code seems inefficient, do you have this for each button? I’d use an array of sound files and create a function to play the sounds based on what view is passed to the OnClickListener. I’ll post another tutorial on how to implement OnClickListners into your activity and just switch based on view id.
Yeah each button is has the code tied to it, I’m really new to java programming and this was the easiest way to get what I was after.
You press a button the code checks if the sound is playing so as to avoid the sounds repeating and then sets up and plays the sound sample.
My problem is that this is obviously inefficient but I can’t see how I can do it any other way.
I too have some questions.
I have a onClickListener/OnClick which plays a soundfile. Later I implemented this ContextMenu by following your guide. Now I want to know how to bring the buttons soundfile
and put it into for example: if(item.getTitle()==”Action 1″){function1(soundfilethatIwanthere);}
I hope you understand my problem/question.
Thanks in advance and thanks alot for this guide!
@Wildheart Baby Posted up a tutorial for grouping your onclicklisteners.
@Hoodis In your context menu you can pass along the ID of the View that has called the context menu (I.E. Which button was long pressed)
In the onCreateContextMenu, this line passes v.getId(), which is the View’s id
menu.add(0, v.getId(), 0, “Action 1″);
In the onContextItemSelected, this line calls the function passing this ID again
function1(item.getItemId());
So in function1 you’d simple need to have something that chooses which sound to act upon based on which View ID was passed to it.
Hope that makes sense
Great tutorial.
Is it possible to have multiple context menus? I have an app with many buttons and I would like each button to have its own context menu. I tried to understand your response to Hoodis, but I wanted to break it down to a separate context menu for each button.
Hi mat, I was wondering if you could maybe take a look at the code i made using your example over at
http://stackoverflow.com/questions/3315269/android-trouble-with-using-multiple-context-menus
I seem to have trouble getting more than one context menu to work :/
@brybam Looks like someone already replied to you. You only need one onCreateContextMenu and onCreateContextMenu and you just need to register all your buttons for a context menu.
Hope you get it working.
Hello, great tutorial!! I have incorporated this into a project, but I am a total newb’ to this and I need some help trying to do something simple. Can you tell me how you would refer to what button was pressed within the called function?
In other words – if I press and hold the first button, how could I then reference the “first button” within function1. Example – I hold down button one. I choose action 1, and it says “Function one called : Button title is It’s gonna blow”.
I am actually trying to take a sounboard that I all ready made, and incorporate your “save as Ringtone” technique.
If you look up a few posts to my reply to @Hoodis, then you will see this:
### QUOTE ###
In your context menu you can pass along the ID of the View that has called the context menu (I.E. Which button was long pressed)
In the onCreateContextMenu, this line passes v.getId(), which is the View’s id
menu.add(0, v.getId(), 0, “Action 1″);
In the onContextItemSelected, this line calls the function passing this ID again
function1(item.getItemId());
So in function1 you’d simple need to have something that chooses which sound to act upon based on which View ID was passed to it.
### UNQUOTE ###
Which can be used to differentiate between the different views. Hope this helps
Hi Matt,
Thanks for all of your tutorials, real food for thought & an inspiration.
Would you mind expanding on you last comment regarding:
“something that chooses which sound to act upon based on which View ID was passed to it”
Look forward to your response, I’ve hit a bit of a wall
I managed to solve the problem with a switch /case query, not perhaps the most efficient solution but it works all the same
)
Along the same lines, how do I make
if (savering(R.raw.sound1)){
and
String filename=”sound1″+”.ogg”;
and
values.put(MediaStore.MediaColumns.TITLE, “sound1″);
dynamic?
I made a soundArray, which works, following your comments to someone else but could not figure out the last part, savering(soundArray[ressound]); to work.
Any help or hints would be gretly appreciated.
Thanks
Hi, I am having trouble with one thing. I am working on a soundboard app. I followed your tutorial and created a GridView of image buttons via a custom ButtonAdapter. Now, how do I register the entire GridView and its children for the context menu? Normally, I would just register each button individually… something along the lines of:
Button btn = (Button) findViewById(R.id.button01);
registerForContextMenu(btn);
The problem is that the buttons created by the custom ButtonAdapter aren’t in the R.java file, so I can’t use that method.
I tried the following code (hoping that registering the gridview would also register the children within it):
GridView gridview = (GridView) findViewById(R.id.gridview);
registerForContextMenu(gridview);
gridview.setAdapter(new ButtonAdapter(this));
I also tried changing around the order of the code above, but nothing seems to work. Can you help me?
@Aaron: Use arrays
@Alex: In your ButtonAdapter you can register for the context menu when you create each view. If you can’t find where let me know and I might be able to find some code.
Thanks, mat. I’ve tried a few things, but I still can’t get it to work right. I keep getting this error:
“The method registerForContextMenu(Button) is undefined for the type ButtonAdapter”
Does your ButtonAdapter extends BaseAdapter ? If not it should, if so, it should work.
Yep, the ButtonAdapter extends BaseAdapter. I still can’t get it to work.
nice post!
thank you
I didnt get the Context menu…..
Well done. What I missed for a long time that might help out a few folks is… you need to set an ID FOR YOUR VIEWs explicitly … yourview.setId(someInt); the view does not have this by default and you will see -1 if its not set yet.
I had Alex’s problem ( method registerForContextMenu not registered)
Fix:
import android.view.MenuItem;
Lance – That doesn’t work for me. Still undefined (I’ve tried cleaning), I’ve even tried importing android.view.ContextMenu.
nice tutorial. but i am facing some problem in adding context menu to a custom view. i have tried to send my custom view’s variable say “upperview” like this
registerForContextMenu(upperview);
i have added rest of the function in my code as shown by this tutorial.
but its nt working. no context menu appear even after long touch on screen.. plz guide if u know anything abt my prob.
Thanks! I now understand Context Menus much better and will be using them in my applications.
After reading a dozen other sites and having all sorts of issues with Eclipse your example was the cleanest and worked on the first try. Thanx.
wow thats a great looking soundboard. wonder if you have the source code up for us to play with
How can i approach to make an circular menu..pls guide me.
thanks
hey ,
i need to open menu on Button click , how to do it that ?
hey , i need to open menu on single Button click , not on long click!!
how to do it that ?
plz reply me on my email id :
justnitnijadhav@gmail.com
For opening a menu on single Button click you also have to add the following code:
linearLayout.setOnClickListener(actionOnClickListener);
private View.OnClickListener actionOnClickListener = new View.OnClickListener() {
public void onClick(View view) {
if(view != null){
view.showContextMenu();
}
}
};
thnx it is really helpful to me……..
Hello Mat,
I’m having trouble differentiating between which button is pressed to bring up the context menu and then get this working into the functions.
Currently I have this;
public void function1(int id){
// save ring tone function
switch (id) {
case test:
Toast.makeText(this, “TEST BUTTON PRESSED”, Toast.LENGTH_SHORT).show();
case test2:
Toast.makeText(this, “TEST2 BUTTON PRESSED”, Toast.LENGTH_SHORT).show();
}
}
Where test and test2 are buttons which bring up the context menu but it just doesn’t seem to be working? Am I totally of course here as I’m very new to Java programming.
Any suggestions?
Thanks.