custom_markers

Custom Markers for Android Google Maps API v2

Recently, I developed an Android app where i used Google Maps API v2 to show the number of car accidents (along with other data) on every street of my city, Lecce.
I had to fetch a json array of streets, each associated to a certain number of accidents, injured people, uninjured people, etc… and then show these data on a map, where users could choose the “category” of data they wanted onto it from a spinner listing all the different categories.

Using a Marker Clusterer was not a good choice, since it would have been an enormous waste of resources (think about it, the app should have put on the map an x number of markers on each street, with x often >50, for y streets) and would not have displayed the real number of incidents/injured/etc when zoomed, at least unless I set the maximum level of zoom as its limit (a huge misuse of a Marker Clusterer).

The most efficient way of accomplishing this task is create a custom drawable from a Drawable resource, put a centered text label in it “on the fly” and then setting the anchor to the map to the exact center of the marker. Follow me in this tutorial, reading the attached code, to learn how I did it.


private GoogleMap map;
private MapFragment mapFragment;

private Double lat = 40.352011;
private Double lng = 18.169139;
private LatLng point = new LatLng ((Double) lat, (Double) lng);

private String title = "This is a Custom Marker!";
private int count = 1;

[...]

mapFragment = ((MapFragment) getFragmentManager().findFragmentById(R.id.mapView));
map = mapFragment.getMap();

[...]

public Bitmap setMarkerDrawable(int number) {
int background = R.drawable.initial_background;

/* DO SOMETHING TO THE ICON BACKGROUND HERE IF NECESSARY */
/* (e.g. change its tint color if the number is over a certain threshold) */

Bitmap icon = drawTextToBitmap(background, String.valueOf(number));

return icon;
}

public Bitmap drawTextToBitmap(int gResId, String gText) {
Resources resources = getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, gResId);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();

if ( bitmapConfig == null ) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
/* SET FONT COLOR (e.g. WHITE -> rgb(255,255,255)) */
paint.setColor(Color.rgb(255, 255, 255));
/* SET FONT SIZE (e.g. 15) */
paint.setTextSize((int) (15 * scale));
/* SET SHADOW WIDTH, POSITION AND COLOR (e.g. BLACK) */
paint.setShadowLayer(1f, 0f, 1f, Color.BLACK);

Rect bounds = new Rect();
paint.getTextBounds(gText, 0, gText.length(), bounds);
int x = (bitmap.getWidth() - bounds.width())/2;
int y = (bitmap.getHeight() + bounds.height())/2;
canvas.drawText(gText, x, y, paint);

return bitmap;
}

[...]

Marker mrk = map.addMarker(new MarkerOptions()
/* SET MARKER TITLE ATRIBUTE */
.title((String) title)
/* SET MARKER POSITION */
.position(point)
/* MAKE IT GENERATE THE MARKER CUSTOM DRAWABLE "ON THE FLY" */
.icon(BitmapDescriptorFactory.fromBitmap(setMarkerDrawable( (int) count )))
/* SET ANCHOR POINT TO MARKER CENTER */
.anchor(0.5f, 0.5f)
);

[...]

Commenti (2)

Leave a Comment

È possibile utilizzare questi tag ed attributi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>