Signup/Sign In

Menu in Android

Have you ever encountered with any of the following menu style in Android?


There are 3 types of menus in Android:

  1. Option Menu
  2. Context Menu
  3. Pop-up Menu

Option Menu

Menu in Android

The options menu is the primary collection of menu items for an activity. It's where you should place actions that have a overall impact on the app, such as Search, Compose Email and Settings.


Context Menu

Menu in Android

A context menu is a floating menu that appears when the user performs a long-click on an element. It provides actions that affect the selected content or context frame.


PopUp Menu

Menu in Android

A popup menu displays a list of items in a vertical list that is anchored(sticked) to the view that invoked the menu. It's good for providing an overflow of actions that relate to specific content or to provide options for a second part of a command.

Note: Actions in a popup menu should not directly affect the corresponding content—that's what contextual actions are for. Rather, the popup menu is for extended actions that relate to regions of content in your activity.


How to create a Menu?

For all menu types mentioned above, Android provides a standard XML format to define menu items. Instead of building a menu in your activity's code, you should define a menu and all its items in an XML menu resource. You can then inflate the menu resource i.e load the XML files as a Menu object in your activity.


Why to use a separate menu resource?

Using a menu resource is a good practice for a few reasons:

  • It's easier to visualize the menu structure in XML.
  • It separates the content for the menu from your application's behavioral code.
  • It allows you to create alternative menu configurations for different platform versions, screen sizes, and other configurations by leveraging the app resources framework.

How to create a menu_file.xml file in menu directory?

To define the menu_file.xml file, first create a menu directory under res folder. This is done by right clicking on res --> new --> Android resource directory.


Menu in Android

Then a new window will appear. Type menu in the directory name and choose menu in the Resource type. Then, click on OK.

Menu in Android


A new menu directory would be made under res directory. Add menu_file.xml file in menu directory by right clicking on menu --> New --> Menu resource file.

Menu in Android


Give the name as menu_file.xml and click on Ok. The menu_file.xml file contains the following tags:

  • <menu>

    It defines a Menu, which is a container for menu items. A <menu> element must be the root node for the file and can hold one or more <item> and <group> elements.

  • <item>

    It creates a MenuItem, which represents a single item in a menu. This element may contain a nested <menu> element in order to create a submenu.

  • <group>

    It is an optional, invisible container for <item> elements. It allows you to categorize menu items so they share properties such as active state and visibility.


menu_file.xml

<?xml version="1.0" encoding="utf-8"?>
  <menu xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:id="@+id/i1"
            android:title="item"
            android:icon="@drawable/item" >

          <!-- "item" submenu -->
          <menu>
              <item android:id="@+id/a"
                    android:title="subitem a"
                    android:icon="@drawable/subitem_a"/>
              <item android:id="@+id/b"
                    android:title="subitem b"
                    android:icon="@drawable/subitem_b" />
          </menu>
      </item>
  </menu>

The <item> element supports several attributes you can use to define an item's appearance and behavior. The items in the above menu include the following attributes:

  • android:id

    A resource ID that's unique to the item, which allows the application to recognize the item when the user selects it.

  • android:icon

    A reference to a drawable to use as the item's icon.

  • android:title

    A reference to a string to use as the item's title.

Now, we have understood how to create a menu.xml and what does it contain. Let's learn how to use it in our Activity.

Making an Option Menu

To make an option menu, we need to Override onCreateOptionsMenu() method as follows:

@Override
  public boolean onCreateOptionsMenu(Menu menu) {
  MenuInflater inflater = getMenuInflater();
      inflater.inflate(R.menu.menu_file, menu);
      return true;
  }
  • MenuInflater inflater = getMenuInflater();

    This gives a MenuInflater object that will be used to inflate(convert our XML file into Java Object) the menu_file.xml file.

  • inflater.inflate(R.menu.menu_file, menu);

    inflate() method is used to inflate the menu_file.xml file.

Handling Click Events

When the user selects an item from the options menu, the system calls your activity's onOptionsItemSelected() method. This method passes the MenuItem selected. You can identify the item by calling getItemId() method, which returns the unique ID for the menu item (defined by the android:id attribute in the menu resource). You can match this ID against known menu items to perform the appropriate action.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    //Handle item selection
    switch (item.getItemId()) {
        case R.id.i1:
            //perform any action;
            return true;
        case R.id.a:
             //perform any action;
            return true;
        case R.id.b:
             //perform any action;
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Note: When you successfully handle a menu item, return true. If you don't handle the menu item, you should call the superclass implementation of onOptionsItemSelected() (The default implementation returns false).

Making Contextual Menu

To make a floating context menu, you need to follow the following steps:

  • Register the View to which the context menu should be associated by calling registerForContextMenu() and pass it the View.

    If your activity uses a ListView or GridView and you want each item to provide the same context menu, you can register yout all items for a context menu by passing the ListView or GridView object to registerForContextMenu() method.

  • Implement the onCreateContextMenu() method in your Activity.

    When the registered view receives a long-click event, the system calls your onCreateContextMenu() method. This is where you define the menu items, usually by inflating a menu resource. For example:

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
                                    ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_file, menu);
    }

    MenuInflater allows you to inflate the menu_file.xml file from a menu resource. The method parameters include the View that the user selected and aContextMenu. ContextMenuInfo object provides additional information about the item selected. If your activity has several views such that each provide a different context menu, you might use these parameters to determine which context menu to inflate.

Handling Click Events

When the user selects a menu item, the system calls onContextItemSelected() method so that you can perform the appropriate action. For example:

@Override
  public boolean onContextItemSelected(MenuItem item) {
      switch (item.getItemId()) {
          case R.id.i1:
              //Perform any action;
              return true;
          case R.id.a:
              //Perform any action;
              return true;
          case R.id.b:
              //Perform any action;
              return true;
          default:
              return super.onContextItemSelected(item);
      }
  }

Making Popup Menu

If you have define your menu_file.xml file in XML, here's how you can show the popup menu:

  • Make an object of PopupMenu, whose constuctor takes the current application Context and the View to which the menu should be anchored.
  • Use MenuInflater to inflate your menu resource into the Menu object returned by PopupMenu.getMenu()
  • Call PopupMenu.show()

For example, here's a button that shows a popup menu when clicked on it:

<Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:onClick="pop" />

The activity can then show the popup menu like this:

public void pop(View v){
          PopupMenu popup = new PopupMenu(this,v);
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.menu_file,popup.getMenu());
          popup.show();
      }

Handling Click Events

To perform an action when the user selects a menu item, you must implement the PopupMenu.OnMenuItemClickListener interface to your Activity and register it with your PopupMenu by calling setOnMenuItemclickListener(). When the user selects an item, the system calls the onMenuItemClick() method in your Activity.

Example:

public void pop(View v){
          PopupMenu popup = new PopupMenu(this,v);
          popup.setOnMenuItemClickListener(this);
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.menu_file,popup.getMenu());
          popup.show();
      }

  @Override
  public boolean onMenuItemClick(MenuItem item) {
      switch (item.getItemId()) {
          case R.id.i1:
              //Perform any action;
              return true;
          case R.id.a:
              //Perform any action;
              return true;
          case R.id.b:
              //Perform any action;
              return true;
          default:
              return false;
      }
  }

Android Code

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.studytonight.menus.MainActivity">

    <TextView
        android:id="@+id/t1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I am context menu"
        android:paddingBottom="30dp"
        android:textAllCaps="true"
        android:textSize="20sp"
 	      />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="pop"
        android:text="I am Pop Menu"
        android:textAllCaps="true"
        />
</LinearLayout>

menu_file.xml

<?xml version="1.0" encoding="utf-8"?>
  <menu xmlns:android="http://schemas.android.com/apk/res/android">

      <item android:id="@+id/i1"
              android:title="Click me to see sub-menu"
              android:icon="@drawable/ic_launcher" >

              <!-- "item" submenu -->
              <menu>
                  <item android:id="@+id/i2"
                      android:title="subitem 1"
                      android:icon="@drawable/ic_launcher"/>
                  <item android:id="@+id/i3"
                      android:title="subitem 2"
                      android:icon="@drawable/ic_launcher" />
              </menu>
          </item>
      </menu>

MainActivity.java

package com.example.akshay.menus;

  import android.content.Intent;
  import android.support.v7.app.AppCompatActivity;
  import android.os.Bundle;
  import android.support.v7.widget.PopupMenu;
  import android.view.ContextMenu;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.widget.TextView;
  import android.widget.Toast;

  import static android.os.Build.VERSION_CODES.N;

  public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);

      //Registering for Context Menu
          registerForContextMenu((TextView)findViewById(R.id.t1));

      }


      @Override
      public boolean onCreateOptionsMenu(Menu menu) {

          MenuInflater mi = getMenuInflater();
          mi.inflate(R.menu.menu_file,menu);
          return true;
      }


      @Override
      public boolean onOptionsItemSelected(MenuItem item) {

          switch (item.getItemId()){
              case R.id.i1:
                  Toast.makeText(this,"Cicked Main Menu",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i2:
                  Toast.makeText(this,"I am sub-menu 1",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i3:
                  Toast.makeText(this,"I am sub-menu 2",Toast.LENGTH_SHORT).show();
                  break;
          }
          return true;
      }


      @Override
      public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
          super.onCreateContextMenu(menu, v, menuInfo);

          MenuInflater mi = getMenuInflater();
          mi.inflate(R.menu.menu_file,menu);
      }


      @Override
      public boolean onContextItemSelected(MenuItem item) {
          switch (item.getItemId()){
              case R.id.i1:
                  Toast.makeText(this,"Clicked Main menu",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i2:
                  Toast.makeText(this,"I am sub-menu 1",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i3:
                  Toast.makeText(this,"I am sub-menu 2",Toast.LENGTH_SHORT).show();
                  break;
          }
          return true;

      }

      public void pop(View v){
          PopupMenu popup = new PopupMenu(this,v);
          MenuInflater mi = getMenuInflater();
          mi.inflate(R.menu.menu_file,popup.getMenu());
          popup.show();

      }


      @Override
      public boolean onMenuItemClick(MenuItem item) {
          switch (item.getItemId()){
              case R.id.i1:
                  Toast.makeText(this,"Clicked Main menu",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i2:
                  Toast.makeText(this,"I am sub-menu 1",Toast.LENGTH_SHORT).show();
                  break;
              case R.id.i3:
                  Toast.makeText(this,"I am sub-menu 2",Toast.LENGTH_SHORT).show();
                  break;
          }
          return true;
      }
  }

You can download the whole project here