Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Draw a location marker on a Google MapView

Author: Johan Pelgrim
Published? false
FormatLanguage: WikiFormat

Problem:

You have a geo location and you want to display it on a Google MapView view object

Solution:

Create an instance of Overlay, draw your marker in it and add it to the MapView overlays. Animate to the given geo point.

Discussion:

Warning The Google Maps V1 API is deprecated; new code should use the V2 API discussed in Recipes 4285 and 4297.

Create a new project called "Location on Map" and use the "Getting Ready for Google Maps Development" recipe to set it up correctly (or simply use the MapTest code from that recipe). If all's well you should have an onCreate like this:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    MapView mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);

}

We are going to make this app a little bit more interesting. First we are going to set the view-type to satellite so we are shown some more recognizable terrain information.

mapView.setSatellite(true);

Run your application to see the effect.

You can add traffic information by calling setTraffic but that works best with map information, not terrain information.

Ok, we can drag- and zoom around on this map, but let's automatically animate to a certain geo location. First of all create a private field called geoPoint and set it to some geo location. Note that the GeoPoint constructor takes integer arguments for the latitude and longitude values and not floating points! You can convert a floating point latitude longitude pair by multiplying it by 1 million or 1E6 in Java terms.

GeoPoint geoPoint = new GeoPoint( (int) (52.334822 * 1E6), (int) (4.668907 * 1E6));

We need a handle to the MapView's MapController to set the zoom-level and animate to a given GeoPoint

MapController mc = mapView.getController();
mc.setZoom(18);
mc.animateTo(geoPoint);

Pretty easy. Fire up the application to see what we've done here. Play around with the zoom-level. What is the minimal value you can set? What is the maximum value?

The technique used to display way markers, your current location and other points of interest, on a map is done with overlays. You can think of an overlay as you've probably seen them in the old days, used in combination with an overhead projector. Overlays can be seen as those transparent plastic sheets, which sometimes had graphics or text on them. You can layer several overlays on a single MapView.

Create a private inner class which extends Overlay and override the draw method.

private class MyOverlay extends com.google.android.maps.Overlay {

    @Override
    public void draw(Canvas canvas, MapView mapView, boolean shadow) {                              // 1
        super.draw(canvas, mapView, shadow);

        if (!shadow) {                                                                              // 2

            Point point = new Point();
            mapView.getProjection().toPixels(geoPoint, point);                                      // 3

            Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.marker_default);   // 4
        
            int x = point.x - bmp.getWidth() / 2;                                                   // 5
        
            int y = point.y - bmp.getHeight();                                                      // 6
        
            canvas.drawBitmap(bmp, x, y, null);                                                     // 7
        }

    }

}

A couple of things are done here.

  1. The draw method has a couple of arguments. The first argument is a handle to an instance of Canvas which we will use to draw our marker on. The second is an instance of MapView on which this overlay is displayed. The third argument is a boolean which indicates whether we are drawing the actual image, or the shadow. In fact, this method is called twice. Once to draw the shadow and once to draw the actual thing you want to draw.
  2. We don't want to draw a shadow
  3. We translate the geo point to actual pixels and store this information in the point variable.
  4. We use the resource identifier to decode it to an actual instance of Bitmap so we can draw it on the canvas
  5. We calculate the x-coordinate of where to draw the marker. We shift it to the left so the center of the image is aligned with the x-coordinate of the geo point
  6. We calculate the y-coordinate of where to draw the marker. We shift it upward so the bottom of the image is aligned with the y-coordinate of the geo point
  7. We draw the bitmap at the calculated x and y locations.

You can use this image as the marker_default.png. Drop it in your ./res/drawable directory

You can manipulate the overlays by calling getOverlays() on the MapView instance.

List<Overlay> overlays = mapView.getOverlays();
overlays.clear();
overlays.add(new MyOverlay());

mapView.invalidate();

To force a view to draw, call the invalidate() method, which is implemented in the View class.

That's it. Fire it up and you should see something like this!

See Also:

Recipe Getting ready for Google Maps development

Download:

The source code for this project can be downloaded from https://github.com/downloads/jpelgrim/androidcookbook/LocationOnMap.zip.
Hamdiovish 2012-08-05 10:33:31.934 >> Thank you very much =)