Skip to content

Android: Context menu example (on long press, gridview)

by mat on April 14th, 2010

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:

Android context menu example

Android context menu 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");
	}

android context menu example

android context menu example

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.

calling a function after a context menu item was pressed

calling a function after a context menu item was pressed

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:

counterstrike 1.6 soundboard context menu

counterstrike 1.6 soundboard context menu


Unreal Tournament soundboard context menu

Unreal Tournament soundboard context menu

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();
    }
}
34 Comments
  1. Wildheart Baby permalink

    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.

  2. 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.

  3. Wildheart Baby permalink

    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.

  4. Hoodis permalink

    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! :)

  5. @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

  6. 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.

  7. brybam permalink

    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 :/

  8. @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.

  9. 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. :-)

  10. 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

  11. Ambiguous Error permalink

    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

  12. Ambiguous Error permalink

    I managed to solve the problem with a switch /case query, not perhaps the most efficient solution but it works all the same :o )

  13. Aaron permalink

    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

  14. Alex permalink

    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?

  15. @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.

  16. Alex permalink

    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”

  17. Does your ButtonAdapter extends BaseAdapter ? If not it should, if so, it should work.

  18. Alex permalink

    Yep, the ButtonAdapter extends BaseAdapter. I still can’t get it to work.

  19. Big Joe permalink

    nice post!
    thank you :)

  20. Aditya permalink

    I didnt get the Context menu…..

  21. Basil permalink

    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.

  22. Lance permalink

    I had Alex’s problem ( method registerForContextMenu not registered)

    Fix:
    import android.view.MenuItem;

    :)

  23. Jon permalink

    Lance – That doesn’t work for me. Still undefined (I’ve tried cleaning), I’ve even tried importing android.view.ContextMenu.

  24. govind9ew permalink

    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.

  25. Thanks! I now understand Context Menus much better and will be using them in my applications.

  26. 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.

  27. droopie permalink

    wow thats a great looking soundboard. wonder if you have the source code up for us to play with

  28. Shubham permalink

    How can i approach to make an circular menu..pls guide me.

    thanks

  29. nitin permalink

    hey ,
    i need to open menu on Button click , how to do it that ?

  30. nitin permalink

    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

  31. 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();
    }
    }
    };

  32. Ranjit(Learning Android) permalink

    thnx it is really helpful to me……..

  33. Chris permalink

    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.

Trackbacks & Pingbacks

  1. stealthcopter.com » Android: Creating a custom Adapter for GridView (ButtonAdapter)

Leave a Reply

Note: I am currently writing my thesis so probably wont have time to reply to your comment
Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS