ZOFTINO.COM

Implementation of Context Menu in Andorid Apps

Context menu is one type of menu that can be implemented in android applications to show list of actions to users. Other types of menus which can be provided in android apps are options menu and popup menu. Context menus are used to display actions which are related to a specific UI element. Context menus allow users to perform certain actions on selected view.

Context menu can be provided in two ways, as fixed top bar and as floating list of menu items.

Floating context menu

To display floating context menu, you need to call activity’s registerForContextMenu method. This method registers the view passed to it for context menu. In activity’s onCreateContextMenu, you can create menu object by inflating menu xml defined for context menu.

Method onContextItemSelected gets called when user clicks context menu items. So, you need to override this method to handle context menu click events and provide appropriate behavior.

android context menu example

Activity

 package com.zoftino.menus;

import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class StoresActivity extends OptionsMenuActivity {

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

        ListView lv = (ListView)findViewById(R.id.stores);
        lv.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, StoresData.arrayOfStores));

        registerForContextMenu(lv);

    }
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
                                    ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
    }
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        Toast toast = null;
        switch (item.getItemId()) {
            case R.id.coupons:
                toast = Toast.makeText(this, "Coupons context item clicked", Toast.LENGTH_LONG);
                toast.show();
                return true;
            case R.id.cashback:
                toast = Toast.makeText(this, "Cashback context item clicked", Toast.LENGTH_LONG);
                toast.show();
                return true;
            case R.id.deals:
                toast = Toast.makeText(this, "Deals context item clicked", Toast.LENGTH_LONG);
                toast.show();
                return true;
            default:
                return super.onContextItemSelected(item);
        }
    }

}
 

Layout xml

 



    

 

Menu xml

 

    
    
    

 

Contextual action mode

Using ActionMode implementation provided by android system, you can create context menus. Context menu displayed using ActionMode is called contextual action mode. Contextual action mode is displayed as bar at top of the screen on pressing contextual mode enabled view for long time. To provide contextual action mode in your app, you need to implement ActionMode call back methods and start action mode.

Contextual action mode can be enabled for single view item or multiple view items.

Contextual action mode on single item

Contextual action mode for single item can be provided by implementing call back methods of ActionMode and starting action mode. First, you need to provide on long click listener for the view you want to display contextual action mode on pressing it for long time. In the long click event handler for the view, you need to start action mode by calling activity’s startActionMode call back method.

StartActionMode method expects ActionMode object as argument. So you need to implement ActionMode and provide instance of it to startActionMode method.

ActionMode call back methods that need to be implemented are onCreateActionMode, onPrepareActionMode and onActionItemClicked. In onCreateActionMode, you can create menu by inflating menu defined in xml. You can handle menu action clicks in onActionItemClicked call back method and take appropriate action based on the menu action clicked.

In below coupons app example on coupons screen, on long pressing store name, contextual action bar is displayed at top of the screen. Below are the screen shot and code.

android actionmode menu example

Activity

 package com.zoftino.menus;

import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class CouponsActivity extends OptionsMenuActivity {

    private boolean isActionMode =false;

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

        ListView lv = (ListView)findViewById(R.id.coupons);
        lv.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, StoresData.arrayOfCoupons));

        TextView tv = (TextView) findViewById(R.id.storeNme);

        tv.setText((String)getIntent().getStringExtra("store"));
        tv.setOnLongClickListener(new View.OnLongClickListener() {
            public boolean onLongClick(View view) {
                if(isActionMode){
                  return false;
                }
                CouponsActivity.this.startActionMode(mActionModeCallback);
                isActionMode = true;
                view.setSelected(true);
                return true;
            }
        });

    }
    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.store_menu, menu);
            return true;
        }
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.topCashback:
                    Toast.makeText(CouponsActivity.this,"View top cashback offers clicked for the selected store", Toast.LENGTH_LONG).show();
                    mode.finish();
                    return true;
                case R.id.vDeals:
                    Toast.makeText(CouponsActivity.this,"View deals clicked", Toast.LENGTH_LONG).show();
                    mode.finish();
                    return true;
                case R.id.topCoupons:
                    Toast.makeText(CouponsActivity.this,"View top coupons clicked", Toast.LENGTH_LONG).show();
                    mode.finish();
                    return true;
                default:
                    return false;
            }
        }
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            isActionMode = false;
        }
    };
}
 

Activity layout xml

 

    

    

 

Menu xml

 

    
    
    

 

Contextual action mode for multiple items

By providing contextual action mode for multiple items, you can allow users to perform actions on selected multiple items. For example, you can enable contextual action mode for list view. On selecting multiple list items, contextual action bar can be displayed allowing user to perform some actions on the selected items.

To implement contextual action mode for list view, you need to set choice mode of the list view to CHOICE_MODE_MULTIPLE_MODAL by calling setChoiceMode on the list view and you need to set listener for the list view by calling setMultiChoiceModeListener method of list view passing MultiChoiceModeListener object. MultiChoiceModeListener has several methods that need to be implemented to create action mode and handle action item click events.

Activity

package com.zoftino.menus;

import android.os.Bundle;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.AbsListView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

public class ShopsActivity extends OptionsMenuActivity implements AbsListView.MultiChoiceModeListener {

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

        ListView lv = (ListView) findViewById(R.id.stores);
        lv.setAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, StoresData.arrayOfStores));

        lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        lv.setMultiChoiceModeListener(this);
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        ListView lv = (ListView) findViewById(R.id.stores);
        switch (item.getItemId()) {
            case R.id.topCashback:
                Toast.makeText(this, getSelectedItems(lv)+" selected", Toast.LENGTH_LONG).show();
                mode.finish();
                return true;
            case R.id.vDeals:
                Toast.makeText(this, getSelectedItems(lv)+" selected", Toast.LENGTH_LONG).show();
                mode.finish();
                return true;
            case R.id.topCoupons:
                Toast.makeText(this,"View top coupons clicked", Toast.LENGTH_LONG).show();
                mode.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.store_menu, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {

    }

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {

    }
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    public static String getSelectedItems(ListView listView) {
        String selectedIds = "";
        SparseBooleanArray selectedItems= listView.getCheckedItemPositions();
        for (int i = 0; i < selectedItems.size(); i++) {
            if (selectedItems.valueAt(i)) {
                selectedIds = listView.getAdapter().getItem(selectedItems.keyAt(i)).toString();

            }
        }
        return selectedIds;
    }
}