Issue
I am writing an app that will show a map with a bunch of markers on it. I want the markers to be dynamic (showing dynamic content on them). Because the markers content is dynamic the size of each marker is different.
I found this in the documentation saying that "Different markers can be returned for different states. The different markers can have different bounds." here: https://developers.google.com/maps/documentation/android/reference/com/google/android/maps/OverlayItem#getMarker(int)
I assume that means that multiple markers on the same overlay can be different sizes. Is that correct?
I have an ArrayList on my overlay (extends BalloonItemizedOverlay). The overlay's createItem() method looks like this:
@Override
protected OverlayItem createItem(final int index)
{
final Person person = people.get(index);
final GeoPoint gp = new GeoPoint(person.getLat(), person.getLng());
final OverlayItem oi = new OverlayItem(gp, person.getName(), person.getName());
oi.setMarker(new PersonDrawable(defaultMarker, person));
return oi;
}
Then in my PersonDrawable
there is a drawable that has a 9 patch as a background image, and then drawing text on top of it:
public PersonDrawable(final Drawable iBackground, final Person person)
{
background = iBackground;
text = person.getName();
padding = new Rect();
if (background instanceof NinePatchDrawable)
{
// This is getting hit, and just sets the value of the padding
final NinePatchDrawable ninePatch = (NinePatchDrawable) background;
ninePatch.getPadding(padding);
}
// set the bounds of the marker
bounds = background.getBounds();
paint = new Paint();
paint.setColor(Color.rgb(255, 255, 255));
paint.setFakeBoldText(true);
paint.setTextSize(30);
// find the bounds of the text
final Rect textBounds = new Rect();
paint.getTextBounds(text, 0, text.length(), textBounds);
// set the left and right bounds to that of the text plus the padding (then center it)
bounds.left = 0 - (textBounds.width() / 2) - padding.left;
bounds.right = 0 + (textBounds.width() / 2) + padding.right;
// set the bounds of the drawable
setBounds(bounds);
}
@Override
public void draw(final Canvas canvas)
{
// when it's time to draw, draw the background
background.draw(canvas);
// then draw the text within the padding
canvas.drawText(text, bounds.left + padding.left, bounds.bottom - padding.bottom, paint);
}
Each marker has a distinct bounds set, even after it's drawn on the overlay its bounds are distinct. The MapView
(or Overlay
) is not reusing the objects from createItem()
. However the Overlay
seems to always pick one marker and assume that is the size for all the markers. Is that just the behavior? Is there something I can do to make it respect the bounds differently for each marker?
Here are some pictures, when it decides to pick a larger marker things turn out ok:
However when it chooses to use the smaller marker as the size:
Solution
The problem is that when a Drawable
is loaded from resources, it is treated as a shareable resources. From the Drawable
documentation:
By default, all drawables instances loaded from the same resource share a common state; if you modify the state of one instance, all the other instances will receive the same modification.
In the OverlayItem
, it is assuming that the Drawable
is going to be the same size throughout. The effect you are seeing is that the last modification to the Drawable
is overriding all previous modifications, so all displays of the Drawable
are showing up exactly the same.
The solution is to prevent sharing of the Drawable
's modifications. You can do this using the mutate()
method in conjunction with multiple loads of the Drawable from a resource. You should do this in conjunction with the PersonDrawable
constructor you have outlined above.
Answered By - Nick Campion
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.