Skip to content

MultiChoiceArrayAdapter tutorial

Kiran Rao edited this page May 27, 2013 · 10 revisions

This tutorial will teach you how to create a very simple list using MultiChoiceArrayAdapter. The list will show a list with some of Manhattan's tallest buildings.

Create a new Android project using Maven or your IDE of choice, and add references to the ActionBarSherlock and MultiChoiceAdapter library projects.

Add a new activity called MainActivity, and make it derive from SherlockActivity. Edit the XML layout for this activity so that it looks like this:

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@android:id/list" />

Now you need an adapter to provide the ListView with items to display. Add the following class to your project:

public class MyArrayAdapter extends MultiChoiceArrayAdapter<String> {

    public MyArrayAdapter(Bundle savedInstanceState, Context context, List<String> items) {
        super(savedInstanceState, context, R.layout.mca__simple_list_item_checkable_1, android.R.id.text1, items);
    }

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

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        if (item.getItemId() == R.id.menu_share) {
            Toast.makeText(getContext(), "Share", Toast.LENGTH_SHORT).show();
            return true;
        }
        return false;
    }

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

Note that you are using the layout R.layout.mca__simple_list_item_checkable_1 for your list items. This is very similar to android.R.layout.simple_list_item_1, except that the contained view implements Checkable and is thus able to change its background to reflect its state.

The menu for the action mode is very simple:

<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/menu_share"
        android:icon="@drawable/ic_social_share"
        android:showAsAction="always"
        android:title="@string/menu_share"/>
</menu>

Now that you have your adapter class ready you can bind it to the ListView. At the end of MainActivity's onCreate method:

ListView listView = (ListView)findViewById(android.R.id.list);
List<String> items = Arrays.asList("One World Trade Center", "Empire State Building", "Bank of America Building", "Chrysler Building");
adapter = new MyArrayAdapter(savedInstanceState, this, items);
adapter.setAdapterView(listView);
adapter.setOnItemClickListener(new OnItemClickListener() {
 public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        Toast.makeText(this, "Item click: " + adapter.getItem(position), Toast.LENGTH_SHORT).show();
    }
});

Two things are worth noting here. First, instead of doing listView.setAdapter() as you'd do with a standard adapter, instead you need to do adapter.setAdapterView(). Second, in order to know when a list item has been clicked you call setOnItemClickListener() on the adapter, not on the list as with a standard adapter.

If you run the application now, it will work alright except for one detail: the checked/unchecked state of list items is lost after a configuration change. Fixing this is simple: just add the following method to your activity:

@Override
protected void onSaveInstanceState(Bundle outState) {
    adapter.save(outState);
}

Customizing the background

By default the list items created this way have a selector that makes their background blue when they are pressed or checked. To change this, just define your own selector and assign it to your list items after inflating them. For instance, the following selector will make your checked items red:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/light_red" android:state_pressed="true"/>
    <item android:drawable="@color/light_red" android:state_checked="true"/>
    <item android:drawable="@android:color/transparent"/>
</selector>

To apply it, override getViewImpl() in your adapter class like this:

    @Override
    protected View getViewImpl(int position, View convertView, ViewGroup parent) {
        View view = super.getViewImpl(position, convertView, parent);
        view.setBackgroundResource(R.drawable.custom_list_item_background);
        return view;
    }

Note that in this case this must be done programmatically because we are using the predefined layout R.layout.mca__simple_list_item_checkable_1. If you are defining your own layout, you can simply set the android:background attribute of your root element.