Android – OverlayItem.setMarker(Drawable icon)
I’ve been developing in Android for a little over two months off and on and am finding certain things I really love and certain things I hate. This is one of the things I hate.
Android provides a nice class to manage drawing OverlayItems to a map called ItemizedOverlay; for instance you might want to display all the people in your contact list on a map. Well, you’d probably want to display a different icon for each person, right? OK, examine the API.
setMarker
public void setMarker(android.graphics.drawable.Drawable marker)Sets the marker to be used when drawing this item on the map. Setting the marker to null will cause the default marker to be drawn (the marker is null by default, so you can just skip this, instead). The marker may be drawn using any combination of the null,
R.attr.state_pressed
,R.attr.state_selected
andR.attr.state_focused
attributes.
OK, that looks perfect. Go ahead and give each OverlayItem the Drawable icon you want to use. Look at the map and… wait a minute. Nothing shows up. Why is that? It works when you haven’t specified the marker…
Well, what this method fails to inform you is that you must define the bounds of a Drawable object before you use it on a map. The definition of Drawable says
The setBounds(Rect) method must be called to tell the Drawable where it is drawn and how large it should be. All Drawables should respect the requested size, often simply by scaling their imagery. A client can find the preferred size for some Drawables with the getIntrinsicHeight() and getIntrinsicWidth() methods.
So to solve the problem we must do the following:
Drawable icon = getResources().getDrawable(someicon); icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); personItem.setMarker(icon);
I wish that an icon defaulted to having its drawable bounds be the rectangle (0, 0, width, height), but you must explicitly define these bounds.
I tried your code on a mapview object. However, absolutely nothing displays on the map. My code is:
public void makemarker(int lat, int lon)
{
p = new GeoPoint(lat,lon);
Projection getcoords;
Point pcon = new Point(0,0);
getcoords = mapView.getProjection();
getcoords.toPixels(p, pcon);
OverlayItem oi = new OverlayItem(p, mapView.getClass().getName(), “”);
Drawable icon = getResources().getDrawable(R.drawable.icon);
icon.setBounds(0, 0, 0 + icon.getIntrinsicWidth(), 0 + icon.getIntrinsicHeight());
oi.setMarker(icon);
}
Any ideas what could be amiss?
Your help would be much appreciated.
You’re missing a step: do this first.
private ItemizedOverlay itemizedOverlay;
private List mapOverlays;
MapView view = …;
mapOverlays = mapView.getOverlays();
Drawable drawable = …;
// Itemized overlay draws all of our people, places, events on map
// Your subclass implementation of ItemizedOverlay should add an add method
itemizedOverlay = …;
mapOverlays.add(itemizedOverlay);
Later:
public void makemarker(int lat, int lon)
{
// Stuff you have in there
// Your subclass for itemizedOverlay should expose add functionality to underlying collection or however you store the overlays.
itemizedOverlay.add(oi);
}
DUDE I LOVE YOU!!
You saved me many ours of hassle
Glad this helped. It seems most people find my blog posts when searching for Android problems… maybe I need to do some more Android development and drive some traffic 🙂
I’ve been looking for a way to correct this exact problem…thanks so much!
Glad this helped! I don’t know why Android doesn’t make this more clear.
Nick
Thanks a lot. Your articles on android + google map are great!
Do you know how I might change the color or shade of the marker when it is focused?
Sorry I haven’t looked into this. You’d probably need a separate drawable for the focused state and switch it out when that state occurs
Thanks a lot for all your efforts; a real time saver. Thanks once again.
Hey Nick! thank you one more time for this tip.. i’ve been wondering like for one week if it was possible afterall to have one overlay with multiple markers…. 😀
Glad everyone finds this tip useful. I really wish they made it a bit more explicit how you’re supposed to do this stuff.. glad people are stumbling onto the blog.
Ah, *thanks a lot* – I should have started to google 2 hours earlier. Can’t believe setMarker() behaves so stupidly and it’s not even mentioned in the method’s docs. Arghh..
Thanks 🙂
GREAT tip! Saved me a ton of wasted effort. Thanks so much!
Glad I found your explanation…it was very frustrating to have my marker not show up. Thanks!
Thank you very much, you saved me.
Awesome, glad this could help, Biggy.
Thank you much.
I have being trying to add a drawable but without any success, Until i came here. adding the android bug page for future reference http://code.google.com/p/android/issues/detail?id=2214
Glad it was of use to you, prakash
Thanks a lot.
Thanks so much, this would’ve driven me crazy! Tthanks to you I solved it in 5 min 🙂
Thanks, this has been very useful. Shame on api’s documentation for this invalidating lack!
❤ !
Thank you so much. It was very useful for me.
Try this:
final Drawable marker = mContext.getResources().getDrawable(R.drawable.android_msg_marker);
item.setMarker(boundCenterBottom(marker));
This was extremely helpful, thank you.
It’s useful. Thank you!
This works however now my shadow is off to the left and higher than it is supposed to. The way I fixed this was to invert the boundaries in such way that i have the negative intrinsict width and height first and the third and fourth parameters are 0, 0..
Thanks for the tip!
I would like to display just the marker, without shadow. It is possible?
Multiple overlays have been driving me crazy and making my app slow. Than you so much for this, you saved me!
A.
Cheers buddy. very useful!
Hey! I know this is kinda off topic however , I’d figured I’d ask.
Would you be interested in trading links or maybe guest authoring a blog post or vice-versa?
My blog discusses a lot of the same topics as yours and I think we could greatly benefit from each other.
If you’re interested feel free to send me an e-mail. I look forward to hearing from you! Superb blog by the way!
What’s the link to your blog?
Thanks, very useful
Fantastic! Thank you for this! 😀
As Danilo mentioned, you can use:
item.setMarker(boundCenterBottom(marker));
I actually used:
item.setMarker(boundCenter(marker));
Hey would you mind sharing which blog platform you’re using? I’m going to start my
own blog in the near future but I’m having a tough time deciding between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your layout seems different then most blogs and I’m looking for something
completely unique. P.S Sorry for being off-topic but I had to
ask!
Great help! Thanks a ton! 🙂
Cheers,
Rohitesh