Sunday, May 8, 2011

Context Menu | Android Developer Tutorial



This is a follow up to the Options Menu Tutorial shared earlier.





To recap, the Context Menu is a floating
list of menu items that appears when a user touches and holds a particular item
displayed in the view, which has a menu associated with it.





Going straight to the example, first I
create a ListView
with names of pens displayed. When one presses and holds one of the names for a
long time, the context menu appears as shown here:





























And when you click on any of the context
menu shown above, the screen that appears is:











Let’s go to the code.





First, the mundane step of creating a Listview
(you can see the ListView
tutorial
for more explanation on this).  


I create a class ShowContextMenu
extending the
ListActivity. In its OnCreate(…) method, I associate the Listview array with the ListAdapater as shown here:





public class ShowContextMenu extends ListActivity {


     





    /** Called
when the activity is first created. */


    @Override


    public void
onCreate(Bundle savedInstanceState) {


        super.onCreate(savedInstanceState);





        setListAdapter(new ArrayAdapter<String>(this,


               
android.R.layout.simple_list_item_1,
getResources().getStringArray(R.array.
names)));





…       


    }



Note that
instead of hard-coding the list items as string array within the class, I have followed
the best practice 
of externalizing the strings into a strings.xml resource
class. Hence I use 
getResources().getStringArray(R.array.names) to retrieve
the array of pen names that I want to display in the List.  The
strings.xml file in the
value folder has this entry:



<string-array name="names">


      <item>MONT Blanc</item>


      <item>Gucci</item>


      <item>Parker</item>


      <item>Sailor</item>


      <item>Porsche Design</item>


      <item>Rotring</item>


      <item>Sheaffer</item>


      <item>Waterman</item>


</string-array>





Once this Listview has been created, now we want to associate a ContextMenu with each of the rows in the Listview Item. i.e. is a user were to long-press one of the items, a menu
should appear. For this we add the following line as well in the
onCreate(..) method.


registerForContextMenu(getListView());





But how do we create the ContextMenu? Whenever the long-press happens, the onCreateContextMenu(…) method is invoked. So,
we need to override this method as shown below:





    public void
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {


      super.onCreateContextMenu(menu, v, menuInfo);


      MenuInflater
inflater = getMenuInflater();


      inflater.inflate(R.menu.context_menu, menu);


    }





Here again, just as in Options
Menu tutorial
, I use a
MenuInflater to create the context menu rather than do it programmatically. This
is certainly a best practice of keeping the concerns separated. The View and
the programming logic are kept separate as meant to be in Android Programming.  The context menu consists of 4 items –
Edit, Save, Delete, View. So, here is how it is defined in the context_menu.xml in
the
res/menu folder:





<menu


  xmlns:android="http://schemas.android.com/apk/res/android">


      <item android:id="@+id/edit"


             
android:title="@string/edit" />


      <item android:id="@+id/save"


           
android:title="@string/save" />


      <item android:id="@+id/delete"


           
android:title="@string/delete" />


      <item android:id="@+id/view"


           
android:title="@string/view" />


</menu>





I have an id that is associated
with each of the menu items that uniquely identifies the menu item selected.
And I have a
String associated with it which is what is displayed on the Menu.





Now that the context menu is created, how
to handle when the menu item is clicked? For this we need to override the
onContextItemSelected(…) method as shown below;





    public boolean onContextItemSelected(MenuItem item) {


      AdapterContextMenuInfo
info = (AdapterContextMenuInfo) item.getMenuInfo();


      String[]
names = getResources().getStringArray(R.array.
names);


      switch(item.getItemId()) {


      case R.id.edit:


            Toast.makeText(this, "You have
chosen the "
+ getResources().getString(R.string.edit) +


                        " context menu option for " + names[(int)info.id],


                        Toast.LENGTH_SHORT).show();


            return true;


      …………………..


      default:


            return super.onContextItemSelected(item);


      }





This is the callback method invoked when a
context menu item is clicked. The callback get the reference to the clicked
menu item as the parameter item.





I use the method item.getItemId() to
retrieve the id of the item clicked. This is the same
id that is defined in
context_menu.xml. So, based on the id, I used a switch statement to jump to the appropriate action. Here the action is
just to toast a message that tell which context menu was clicked for which ListView
item. How do I retrieve the ListView item clicked?





Extra information about the menu is
returned by calling
item.getMenuInfo().  Info.id would be the
ListView id. I use this id to retrieve the name of the pen  as in
names[(int)info.id]





That is it. Do you want the complete code? Here
it is.

No comments:

Post a Comment