Monday, March 1, 2010


Responding to zooms and pans in Android's MapView

There's a curious lacuna in Android's MapView API: it's (relatively) easy to display a map, and overlay items atop a map; it's (relatively) easy to detect when an overlay item has been touched; but there's no straightforward way to work out when the user has touched anywhere else on the map. Because of the way MapView works, the usual onTouchListener() solution only works for one touch, and then fails.

There is, however, a solution. Not a pretty one, but it works. The solution is to use your own subclass of MapView:

public class ITRMapView extends MapView {
public ITRMapView(android.content.Context context, android.util.AttributeSet attrs) {
super(context, attrs);

public ITRMapView(android.content.Context context, android.util.AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

public ITRMapView(android.content.Context context, java.lang.String apiKey) {
super(context, apiKey);

and within that subclass, override onTouchEvent. You're probably only interested in the UP action:

public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction()==MotionEvent.ACTION_UP) {
//do your thing
return super.onTouchEvent(ev);

But what if you want to detect zoom actions as well as touches? Simple, thought I: just override onDraw() and do the same thing. But you can't - MapView's onDraw() is final!

Catastrophe? Not quite. It turns out that overriding dispatchDraw() works just fine:

int oldZoomLevel=-1;

public void dispatchDraw(Canvas canvas) {
if (getZoomLevel() != oldZoomLevel) {
//do your thing
oldZoomLevel = getZoomLevel();

Et voila - you can programmatically detect and respond when the user pans and/or zooms your map. Really not so hard after all.

Labels: , , , , , , , , , ,

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]