Using the ItemizedOverlay and OverlayItem

1258 views
Skip to first unread message

Reto

unread,
Aug 25, 2008, 12:29:36 PM8/25/08
to Android Developers
I've been trying to use the ItemizedOverlay and OverlayItem classes in
the 0.9 Beta to simulate map markers but have been having some
problems getting it to display on the map.

Once I've implemented my own ItemizedOverlay (and overriden
createItem), creating a new instance of my class seems to work (I can
extract OverlayItems from it) but adding it to the overlay list for
one of my maps doesn't seem to do anything.

I've included the code for adding the ItemizedOverlay to the map, and
the ItemizedOverlay implementation itself is also included. Have I
done something wrong or is this functionality not yet available?

// Add the ItemizedOverlay to the Map
private void addItemizedOverlay() {
Resources r = getResources();
mapView = (MapView)findViewById(R.id.map_view);
List<Overlay> overlays = mapView.getOverlays();

MyItemizedOverlay markers = new
MyItemizedOverlay(r.getDrawable(R.drawable.icon));
overlays.add(markers);

OverlayItem oi = markers.getItem(0);
markers.setFocus(oi);
mapView.postInvalidate();
}

Where MyItemizedOverlay is defined as:

public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem> {
public MyItemizedOverlay(Drawable defaultMarker) {
super(defaultMarker);
populate();
}

@Override
protected OverlayItem createItem(int index) {
Double lat = (index+37.422006)*1E6;
Double lng = -122.084095*1E6;
GeoPoint point = new GeoPoint(lat.intValue(), lng.intValue());

OverlayItem oi = new OverlayItem(point, "Marker", "Marker Text");
return oi;
}

@Override
public int size() {
return 5;
}
}

marcel-182

unread,
Aug 26, 2008, 1:50:19 AM8/26/08
to Android Developers
Hi,

Same problem here. I added two items and I found out that even the
draw() method from ItemizedOverlay is called but there is nothing on
my map view. My code is quite equal to yours.

Guillaume Perrot

unread,
Aug 26, 2008, 11:52:29 AM8/26/08
to Android Developers
Hi,
I have the same problem.
The draw function is called, I tried to override it, I even added a
bitmap in the top left corner for test purposes, I see my dummy bitmap
but no items...

Chris Chiappone

unread,
Aug 27, 2008, 2:49:13 PM8/27/08
to android-d...@googlegroups.com
Same problem here, i converted code normal overlay code that worked in
order to use the "recommended" ItemizedOverlay. Can anyone confirm
that this is a bug or are we just doing something wrong.

Thanks.
--
~chris

Guillaume Perrot

unread,
Aug 28, 2008, 5:20:01 AM8/28/08
to Android Developers
Here is a code which is actually working, but with manual draw, you
can imitate my workaround for now.
I hope an official answer will come up fast...

/** Map layer displaying contact locations */
public class LocationOverlay extends
ItemizedOverlay<LocationOverlayItem>
{
/** Contacts with known location */
private final List<Contact> mContacts;

/*
* FIXME fields to manually draw items, we don't know how to make
* ItemizedOverlay actually work
*/
private Bitmap mBubbleBitmap;
private Paint mInnerPaint;
private Paint mBorderPaint;
private TextPaint mTextPaint;
private static final int TEXT_OFFSET_X = 10;
private static final int TEXT_OFFSET_Y = 15;
private static final int INFO_WINDOW_HEIGHT = 25;

/** Create a new instance */
public LocationOverlay()
{
super(UbikIMApplication.getApplicationResources().getDrawable(
R.drawable.bubble));

/* Get contacts with location */
mContacts = new ArrayList<Contact>();
for (Contact contact : ContactManager.getInstance().getContacts())
if (contact.getLocation() != null)
mContacts.add(contact);

/* Populate */
populate();

/* FIXME manual draw managing relating code */

/* Decompress bubble bitmap */
mBubbleBitmap = BitmapFactory.decodeResource(UbikIMApplication
.getApplicationResources(), R.drawable.bubble);

/* Init painter used to draw the inner of the info window */
mInnerPaint = new Paint();
mInnerPaint.setARGB(225, 75, 75, 75);
mInnerPaint.setAntiAlias(true);

/* Init painter used to draw the border of the info window */
mBorderPaint = new Paint();
mBorderPaint.setARGB(255, 255, 255, 255);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setStyle(Style.STROKE);
mBorderPaint.setStrokeWidth(2);

/* Init painter used to draw the text inside the info window */
mTextPaint = new TextPaint();
mTextPaint.setARGB(255, 255, 255, 255);
mTextPaint.setAntiAlias(true);
}

@Override
protected LocationOverlayItem createItem(int i)
{
return new LocationOverlayItem(mContacts.get(i));
}

@Override
public int size()
{
return mContacts.size();
}

@Override
public void draw(Canvas canvas, MapView mapView, boolean shadow)
{
/* FIXME manual draw because automatic doesn't seem to work */

/* Retrieve map view projection to compute coordinates */
Projection projection = mapView.getProjection();

/* For all contacts with location (including self) */
for (int index = size() - 1; index >= 0; index--)
{
OverlayItem item = getItem(index);
String title = item.getTitle();
Point point = projection.toPixels(item.getPoint(), null);

/* Draw bubble */
canvas.drawBitmap(mBubbleBitmap, point.x -
mBubbleBitmap.getWidth() / 2,
point.y - mBubbleBitmap.getHeight(), null);

/* Compute info window geometry */
int INFO_WINDOW_WIDTH = getTextWidth(title) + TEXT_OFFSET_X * 2;
RectF infoWindowRect = new RectF(0, 0, INFO_WINDOW_WIDTH,
INFO_WINDOW_HEIGHT);
int infoWindowOffsetX = point.x - INFO_WINDOW_WIDTH / 2;
int infoWindowOffsetY = point.y - INFO_WINDOW_HEIGHT
- mBubbleBitmap.getHeight() - 2;
infoWindowRect.offset(infoWindowOffsetX, infoWindowOffsetY);

/* Draw inner info window */
canvas.drawRoundRect(infoWindowRect, 5, 5, mInnerPaint);

/* Draw border for info window */
canvas.drawRoundRect(infoWindowRect, 5, 5, mBorderPaint);

/* Draw user name in the info window */
canvas.drawText(title, infoWindowOffsetX + TEXT_OFFSET_X,
infoWindowOffsetY + TEXT_OFFSET_Y, mTextPaint);
}

super.draw(canvas, mapView, shadow);
}

/* FIXME manual draw related function */
/** @return text width in pixels that the text paint will use to
draw text */
private int getTextWidth(String text)
{
int count = text.length();
float[] widths = new float[count];
mTextPaint.getTextWidths(text, widths);
int textWidth = 0;
for (int i = 0; i < count; i++)
textWidth += widths[i];
return textWidth;
}

@Override
protected boolean onTap(int index)
{
setFocus(getItem(index));
return true;
}

@Override
protected boolean hitTest(LocationOverlayItem item, Drawable marker,
int hitX, int hitY)
{
return super.hitTest(item, marker, hitX, hitY +
mBubbleBitmap.getHeight()
/ 2);

Guillaume Perrot

unread,
Aug 28, 2008, 5:24:19 AM8/28/08
to Android Developers
Contact and LocationOverlayItem (extending OverlayItem to set fields
based on a Contact) are custom classes I created for my application,
they're not important to understand my code.

Chris Chiappone

unread,
Aug 28, 2008, 11:14:08 AM8/28/08
to android-d...@googlegroups.com
Seems like not much point in overriding ItemizedOverlay, what added
functionality do you really get then just overriding Overlay?
--
~chris

marcel-182

unread,
Sep 1, 2008, 4:03:31 PM9/1/08
to Android Developers
Hi everyone,

I finally got this thing working. Just set the bounds of the marker to
be drawn and that's it!

Sample:
Drawable defaultMarker =
getResources().getDrawable(R.drawable.map_marker_red);
defaultMarker.setBounds(0, 0, defaultMarker.getIntrinsicWidth(),
defaultMarker.getIntrinsicHeight());
mMapView.getOverlays().add(new DemoOverlay(defaultMarker)); //
DemoOverlay is of course an ItemizedOverlay

I made a small demo showing one OverlayItem and how to handle tap-
events. If someone is interested:
http://www.marcelp.info/2008/09/01/android-itemizedoverlay-demo/

Regards, Marcel

Chris Chiappone

unread,
Sep 2, 2008, 12:03:09 PM9/2/08
to android-d...@googlegroups.com
Marcel,

Thanks for that seems to work as you described. The only thing that
doesn't seem right is the way the map draws the markers shadow. Any
idea on how to correct that.

Thanks.

--
~chris

marcel-182

unread,
Sep 2, 2008, 12:21:23 PM9/2/08
to Android Developers
No, I don't know how to change that behavior.

But if you don't like the shadow just disable it :-):
@Override
public void draw(Canvas pCanvas, MapView pMapView, boolean pShadow) {
super.draw(pCanvas, pMapView, false);

Cretin45

unread,
Sep 2, 2008, 2:12:36 PM9/2/08
to Android Developers
I got the shadow to draw properly by calling
boundCenterBottom(Drawable);

@Override
public void draw(Canvas arg0, MapView arg1, boolean arg2) {
super.draw(arg0, arg1, arg2);
MyItemizedOverlay.boundCenterBottom(defaultMarker);
}

Not sure if this is the "right" way. But, it is working.

Peter Stevenson

unread,
Sep 3, 2008, 6:09:40 AM9/3/08
to android-d...@googlegroups.com
try changing

private GeoPoint mRandomPoint = new GeoPoint(5309691, 8851933);
to some thing like this
currentPoint = new GeoPoint((int) (-43.2973 * 1000000), (int) (172.5929
* 1000000));
the map is draw much faster

peter


Guillaume Perrot

unread,
Sep 4, 2008, 5:51:27 AM9/4/08
to Android Developers
OK overlay items are drawn with the setBounds trick.
But overlay title or snippet is never drawn even if we tap on it. How
to use these overlay items fields ?

On Sep 3, 12:09 pm, Peter Stevenson <cyber.sp...@xtra.co.nz> wrote:
> Chris Chiappone wrote:
> > Marcel,
>
> > Thanks for that seems to work as you described.  The only thing that
> > doesn't seem right is the way the map draws the markers shadow.  Any
> > idea on how to correct that.
>
> > Thanks.
>

Chris Chiappone

unread,
Sep 4, 2008, 11:35:35 AM9/4/08
to android-d...@googlegroups.com
I had to manually draw those inside the onTap method.

--
~chris

Guillaume Perrot

unread,
Sep 11, 2008, 9:17:27 AM9/11/08
to Android Developers
I also manually draw titles but I have problem with ordering them
because when calling super(), all bubbles are drawn at once, then (or
before) I can draw info window. What I want to do is draw a bubble
(super.draw) then an info window then another bubble then another info
window etc....
It would be great to have a draw method in OverlayItem class to
override...

Guillaume Perrot

unread,
Sep 12, 2008, 6:51:46 AM9/12/08
to Android Developers
I use the following drawable to show a different state for the focused
item but I found no documentation about drawables described by XML
items:

<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/bubble_normal" />
<item
android:state_focused="true"
android:drawable="@drawable/bubble_focused" />
</selector>

I only see the bubble_normal even if the overlay item is focused.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages