Maps, ItemizedOverlay, and You!

This post synthesizes a discussion of getting ItemizedOverlay to work held on the [android-developers] Google Group. Many thanks to the folk who chimed in on that thread (particularly MarcelP), and for everyone on the Android Google Groups who have been helping other developers in need.

If you have ever used the full-size edition of Google Maps, you are probably used to seeing things overlaid atop the map itself, such as “push-pins” indicating businesses near the location being searched. In map parlance — and, for that matter, in many serious graphic editors — the push-pins are on a separate layer than the map itself, and what you are seeing is the composition of the push-pin layer atop the map layer.

Android’s mapping allows you to create layers as well, so you can mark up the maps as you need to based on user input and your application’s purpose.

Any overlay you want to add to your map needs to be implemented as a subclass of Overlay. There is an ItemizedOverlay subclass available if you are looking to add push-pins or the like; ItemizedOverlay simplifies this process.

To attach an overlay class to your map, just call getOverlays() on your MapView and add() your Overlay instance to it:

As the name suggests, ItemizedOverlay allows you to supply a list of points of interest to be displayed on the map — specifically, instances of OverlayItem. The overlay, then, handles much of the drawing logic for you. Here are the minimum steps to make this work:

In the constructor, build your roster of OverlayItem instances, and call populate() when they are ready for use by the overlay

Implement size() to return the number of items to be handled by the overlay

Override createItem() to return OverlayItem instances given an index

When you instantiate your ItemizedOverlay subclass, provide it with a Drawable that represents the default icon (e.g., push-pin) to display for each item

The marker from the above code snippet is the Drawable used for the last bullet above.

You may also wish to override draw() to do a better job of handling the shadow for your markers. While the map will handle casting a shadow for you, it appears you need to provide a bit of assistance for it to know where the “bottom” of your icon is, so it can draw the shadow appropriately.

For example, here is an ItemizedOverlay subclass (SitesOverlay) that puts four pins on a map of Manhattan:

If we open up a MapView and use that overlay, you would see something like this:

An Overlay subclass can also implement onTap(), to be notified when the user taps on the map, so the overlay can adjust what it draws. For example, in full-size Google Maps, clicking on a push-pin pops up a bubble with information about the business at that pin’s location. With onTap(), you can do much the same in Android.

The onTap() method for ItemizedOverlay receives the index of the OverlayItem that was clicked. It is up to you to do something worthwhile with this event.

In the case of SitesOverlay, as shown above, onTap() just tosses up a short Toast with the “snippet” from the OverlayItem, returning true to indicate we handled the tap.