Skip to content
ManuelPeinado edited this page May 5, 2013 · 2 revisions

This tutorial will teach you how to use MultiChoiceAdapter to implement a grid of photos similar to the one in the stock Gallery app. This will be the final result:

Example Image

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

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

<GridView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    android:horizontalSpacing="4dp"
    android:verticalSpacing="4dp"
    android:numColumns="2"
    android:stretchMode="columnWidth" />

Now you need an adapter to provide the ListView with items to display. Each item will be an instance of the following class:

public class Building {
    public String name;
    public Drawable photo;

    public Building(String name, Drawable photo) {
        this.name = name;
        this.photo = photo;
    }
}

The layout for the items will be quite simple:

<com.manuelpeinado.multichoiceadapter.CheckableImageView   
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="centerCrop"/>

We cannot use an ImageView because the root of the item's layout must implement the Checkable interface. Luckily, the library includes a version of ImageView that does just that. An interesting thing about this class is that it doesn't use the android:background for its selector, since that would be obscured by the image. Instead, it draws the selector over the image, just like a ListView does in the drawSelectorOnTop mode. By default this selector is a semitransparent blue with opaque borders, as you can see in the screenshot above. You can customize it quite easily by defining your own selector in XML (don't forget the checked state) and assigning it to the android:foreground attribute of your CheckableImageView element.

Next you will create the adapter class itself:

public class GalleryAdapter extends MultiChoiceBaseAdapter {
    private List<Building> buildings;

    public GalleryAdapter(Bundle savedInstanceState, List<Building> buildings) {
        super(savedInstanceState);
        this.buildings = buildings;
    }

    @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;
    }

    @Override
    public int getCount() {
        return buildings.size();
    }

    @Override
    public Building getItem(int position) {
        return buildings.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    protected View getViewImpl(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            int layout = R.layout.gallery_item;
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(layout, parent, false);
        }
        ImageView imageView = (ImageView) convertView;
        Building building = getItem(position);
        imageView.setImageDrawable(building.photo);
        return imageView;
    }
}

Now it's time to bind this adapter to the ListView. Add this at the end of your activity's onCreate method:

GridView gridView = (GridView)findViewById(android.R.id.list);
List<Building> buildings = // Create list of buildings, check sample project to see how it's done
adapter = new GalleryAdapter(savedInstanceState, buildings);
adapter.setAdapterView(gridView);
adapter.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
        Toast.makeText(this, "Item click: " + adapter.getItem(position).name, Toast.LENGTH_SHORT).show();
    }
});

Note how we are calling setOnItemClickListener on the adapter, not on the list.

Finally, you shouldn't forget to persist your adapter's state:

@Override
protected void onSaveInstanceState(Bundle outState) {
    adapter.save(outState);
}
Clone this wiki locally