Map overlays

I have explained in an earlier post how to display Google Maps. In Dublin Buzz, every map opens centred on the sight and also contains a red dot and text label for the sight. This was more complicated to achieve that it looks! In fact, Android Google Maps use a concept called “Overlays” to provide this kind of functionality. My overlay also allows users to click on it and to see some details about the sight, such as its phone number. Let’s see how the code does that.

It is all contained in the MapLabel.java file, downloadable here: MapLabel.
All map overlays are subclasses of the Overlay object (it gets slightly more complex when you want multiple overlays, but for now, it is sufficient to understand the simpler case of just using one overlay on a map). We must override the draw() method of the Overlay to provide the custom drawing functionality. The Overlay superclass handles the rest.

package com.tony.buzz;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.*;
import com.google.android.maps.*;

/**
 * Displays a simple label with the name of the sight in red and a red dot over the map
 * @author Tony Scannell
 */
public class MapLabel extends Overlay {

	private GeoPoint sight = null;
	private String name = null;
	private Context mapviewer = null;
	private String details = null;

	/**
	 * Constructs a map overlay at the point specified and with the text displayed
	 * @param thePlace The geographic point to display the label at
	 * @param desc The label to append
	 */
	public MapLabel(GeoPoint thePlace, String desc, String details, Context activity)
	{
		sight = thePlace;
		name = desc;
		this.details = details;
		mapviewer = activity;
	}

	/**
	 * Overrides the draw method to provide the custom drawing of the label and red dot indicating where a sight is
	 */
	@Override
	public void draw (Canvas canvas, MapView map, boolean shadow)
	{
		// Start by converting the geopoint to a pixel location on the map (held in mypt)
		Projection projection = map.getProjection();
		Point mypt = new Point();
		projection.toPixels(sight, mypt);

		// Use this paint to draw the dot and write the text label
		Paint pt = new Paint();
		pt.setTextSize(25);
		pt.setARGB(250, 255, 0, 0);
		pt.setAntiAlias(true);
		pt.setFakeBoldText(true);

		int rad = 5;
		// Draws a red dot
		RectF oval = new RectF(mypt.x-rad, mypt.y-rad, mypt.x+rad, mypt.y+rad);
		canvas.drawOval(oval, pt);
		// Writes out the text label for the sight
		canvas.drawText(name, mypt.x+rad, mypt.y, pt);
	}

	/**
	 * Some tap on the surface displays the details for the sight (e.g. address and phone)
	 */
	@Override
	public boolean onTap (GeoPoint point, MapView map)
	{
	    AlertDialog.Builder builder = new AlertDialog.Builder(mapviewer);
	    builder.setTitle(name);
	    builder.setMessage(details);
     	    builder.setCancelable(true);
	    builder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
	    public void onClick(DialogInterface dialog, int id) {
	    	dialog.cancel();
	        }
	    });
     	AlertDialog alert = builder.create();
	    alert.show();
	    return true;
	}
}

The essence of what needs to be done is to convert a geographical location (a GeoPoint in Android) to a specific pixel on the map displayed. These three lines of code get a projection object from the map view object, and then uses the toPixels method to convert a GeoPoint location to pixels on the map.

Projection projection = map.getProjection();
Point mypt = new Point();
projection.toPixels(sight, mypt);

The rest of the code uses a Paint object to specify colour and text size. The draw() method (of which this code is a part) is an override of the existing Overlay object’s draw() method and it receives a Canvas argument, to be used in drawing text and shapes on. Basically, I use the point object calculated earlier and draw an oval (actually, a circle, but using the drawOval method) onto the canvas, followed by the text. And that’s it.

To handle users taps on the map, we simple override the onTap() method. The onTap() method opens a dialog with an OK button and the sight’s details displayed.

Here’s a map displayed with the text and red dot.

Advertisements
This entry was posted in Android, Android development, Mobile Apps. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s