Richard Sewell
Richard Sewell

Reputation: 101

Android Maps API v2 - approaches to marker rotation?

We're porting an app from the v1 Maps API to the v2 API, and having trouble with markers.

We need markers that point in a specific geographic direction. In V1, we could build the bitmap pointing in the right direction at draw time, but in V2 the marker bitmap can't be changed.

I'm not sure if the best approach is to destroy and re-build all our markers when the map is rotated (which sounds like a performance problem), or to try drawing them all ourselves. That could be via a TileOverlay or via a view of our own that we sat on top of the map.

I don't really like any of these approaches. Has anyone tried any of them ?

UPDATE:

I've tried drawing via a view of our own, but that was far too laggy when the map was dragged.

I'm now destroying & recreating the markers, but that is (as expected) a performance problem, taking ~2000mS to update 60 markers.

Upvotes: 4

Views: 3768

Answers (4)

kevinpelgrims
kevinpelgrims

Reputation: 2156

Good news everyone! Google has added rotation to the Maps API, so we don't have to roll our own implementations anymore.

They have also added flat markers, which I guess is more related to the original question. A flattened marker will always stay in the orientation it was originally drawn on the map: https://developers.google.com/maps/documentation/android/marker#flatten_a_marker

The only requirement is that you reference the latest version of Google Play Services.

Upvotes: 5

Blake Hair
Blake Hair

Reputation: 151

I had a similar problem where I had markers that needed to rotate. My solution was to have the object the marker represented be responsible for generating the marker. I have a few methods in the object that look like:

protected Marker getMarker(GoogleMap map) {
    if (this.marker == null) {
        marker = map.addMarker(new MarkerOptions().position(location).
            icon(BitmapDescriptorFactory.fromBitmap(BusMarkerImageFactory.
            getMarkerIcon(heading))));
    }
    return marker;
}

protected void updateMarker(GoogleMap map) {
    if (marker != null) {
        rotateIcon();
        marker.setPosition(location);
    } else {
        getMarker(map);
    }

private void rotateIcon() {
    marker.setIcon(BitmapDescriptorFactory.
        fromBitmap(BusMarkerImageFactory.getMarkerIcon(heading)));
}

This is from a system that draws buses with the markers pointing in the direction they are heading, so of course, your code will be different, but the concept is very similar. Instead of rebuilding the entire marker you're keeping a reference to it somewhere and then simply resetting the icon.

Of course, drawing all those bitmaps for minor changes is a drain on memory. I used a flyweight pattern in the (incorrectly named) BusMarkerImageFactory to keep 16 images for 16 possible heading ranges. It is a static class that simply takes in the heading and returns the image that I've mapped to that range.

Upvotes: 1

Ridcully
Ridcully

Reputation: 23655

I'm also rewriting my app (Runbot) for the new API and had to figure out how to create custom markers representing milestones (like 1km, 2km, ...) and how to show or show not all of them depending on the zoom level. I had a custom drawable that I used for the v1 API and what I do now to render the markers is about this (Position is a class of my own that holds the position and further information; all needed here is its LatLng property):

private void addMarker(Position p, MilestoneDrawable milestone) {
    if (mMarkers.containsKey(p)) {
        mMarkers.get(p).setVisible(true);
    } else {
        Marker m = mMap.addMarker(new MarkerOptions()
            .position(p.latLng)
            .icon(BitmapDescriptorFactory.fromBitmap(Util.drawableToBitmap(milestone)))
            .anchor(0.5f, 1.0f) // bottom center
            );
        mMarkers.put(p, m);
    }
}

Besides creating and adding the custom markers, what you see is that I keep the markers in a HashMap so I do not have to destroy and create them all the time. When it comes to zooming and deciding which ones to show, I first set all of the markers to invisible and than call addMarker() for those I want to be shown, and those which I already have in the HashMap I simply make visible again.

I hope this helps you a bit. I have a bit of mixed feelings towards the new API...

Upvotes: 1

Moh Sakkijha
Moh Sakkijha

Reputation: 2705

can't you use addMarker(new MarkerOptions()) method ?

If you need a custom marker you can create an implementation of InfoWindowAdapter and use that implementation like mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());

here is the documentation for InfoWindowAdapter

Upvotes: 0

Related Questions