Android osmdroid overlayItem tap detected with offset - android

I use
+android 4.2
+osmdroid-android-3.0.9
+sherlock action bar
I need show on map item. On click at this item show dialog. But has trouble onItemSingleTapUp raised with offset.
osmapview = (MapView) findViewById(R.id.osmapview);
osmapview.setBuiltInZoomControls(true);
osmapview.setTileSource(TileSourceFactory.MAPNIK);
osmapview.setClickable(false);
final MapController mc = osmapview.getController();
mc.setZoom(14);
ArrayList<OverlayItem> overlayItems = new ArrayList<OverlayItem>();
CustomOverLay overlays = new CustomOverLay(overlayItems, getResources().getDrawable(R.drawable.marker96));
GeoPoint p = new GeoPoint(48.427677, 35.239871);
OverlayItem overlayItem = new OverlayItem("Title1", "Description1", p);
overlays.addItem(overlayItem);
public class CustomOverLay extends ItemizedIconOverlay<OverlayItem> {
public CustomOverLay(ArrayList<OverlayItem> overlayItems, Drawable drawable) {
super(overlayItems, drawable, new OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
L.e("++" + 1);
return false;
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
L.e("++" + 2);
return false;
}},
new DefaultResourceProxyImpl(getApplicationContext()));
}
#Override
protected boolean onSingleTapUpHelper(int index, OverlayItem item, MapView mapView) {
L.e("+ " + item.mTitle);
return super.onSingleTapUpHelper(index, item, mapView);
}
}
map drawed - ok
marker drawed - ok
tap on marker - failed
if tap bottom (very bottom) of marker - ok
What is the cause the offset?

Turn off hardware acceleration in your manifest or in code. See the samples application for examples on how to do this. There is better hardware acceleration support in 3.0.10.

It's error in osmdroid-android-3.0.9
use osmdroid-android-3.0.8
Issue

Related

Android Google Maps onTap is not called

Somehow when I tap on the Icon I added to the Map the onTap Event is not called can somebody tell me why :S? Its a overlay with all Users I add to the Map they all have the same Icon but all diffrent Titles. But when I tap nothing happens I also tried Logging it if something happens with Log.d but nothing happens. This is the code:
private class MyUsersOverlay extends ItemizedOverlay<OverlayItem> {
private List<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
public MyUsersOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
public void addOverlayItem(int lat, int lon, String title, String... message) {
GeoPoint point = new GeoPoint(lat, lon);
OverlayItem overlayItem = new OverlayItem(point, title, null);
addOverlayItem(overlayItem);
}
public void addOverlayItem(OverlayItem overlayItem) {
mOverlays.add(overlayItem);
populate();
}
#Override
protected boolean onTap(int index)
{
Log.d("Test Message", "It works");
OverlayItem item = mOverlays.get(index);
//Do stuff here when you tap, i.e. :
//AlertDialog.Builder dialog = new AlertDialog.Builder(cMainActivity);
//dialog.setTitle(item.getTitle());
//dialog.setMessage(item.getSnippet());
//dialog.show();
Toast.makeText(cMainActivity, item.getTitle(),
Toast.LENGTH_SHORT).show();
return true;
}
#Override
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow)
{
super.draw(canvas, mapView, shadow);
if (shadow == false)
{
//cycle through all overlays
for (int index = 0; index < mOverlays.size(); index++)
{
OverlayItem item = mOverlays.get(index);
// Converts lat/lng-Point to coordinates on the screen
GeoPoint point = item.getPoint();
Point ptScreenCoord = new Point() ;
mapView.getProjection().toPixels(point, ptScreenCoord);
//Paint
Paint paint = new Paint();
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(10);
paint.setARGB(150, 0, 0, 0); // alpha, r, g, b (Black, semi see-through)
//show text to the right of the icon
canvas.drawText(item.getTitle(), ptScreenCoord.x, ptScreenCoord.y+10, paint);
}
}
}
Did you remember to put mapView.setClickable(true); in your oncreate() methode?
The problem isn't in the code above, but somewhere else. You have another view stealing the touch events from your ´ItemizedOverlay`.
Possibilities
You may be playing with dispatchTouchEvent() in your map activity and returning true all the time, informing that events have been used and no further dispatch should occour.
In the layout where you define MapView, you may have added a view after MapView that is parcialy covering it. Motion events are dispatched starting from last added view.
You may have added another MapView overlay that is covering the ItemizedOverlay.
It can be an issue if you want to click on an overlay AND have events for clicking on the general mapview. If that is what you are trying to achieve then check out this tutorial. Even if you are having a different issue the tutorial might help you fix your problem.

Navigation between overlays

It´s possible that overlays on a map could receive focus from DPAD/Tab?
I have two fragments, a listview and mapview, I want to get focus from the drawable of the overlay, but I´m not sure if it´s possible...
Yes, you can move from one overlay item on MapView to other but there are few things which you should consider.
If you want your MapView to steer according to the Dpad directions while pressing up/down/left on Dpad, then your map will go up/down/left direction showing the map and you wont able to Dpad on overlay items since MapView is having the focus.
But if you want overlay items to be focused, then you have to manually define which overlay item it should focus on which D-Pad direction using setFocus, nextFocus and getFocus methods of ItemizedOverlay class.
Also you said you have listview and MapView in your activity and in order to get the focus back to listview or any other view which is outside MapView will also have to be done programmatically and it could be little tricky.
You can use StateListDrawable to define the different states on overlaid drawable for focus, pressed and default state.
Hope this answers your query.
I created a sample activity below. Most of the code comes from the MapView tutorial found here: http://developer.android.com/resources/tutorials/views/hello-mapview.html
The 'focus code' is in the onKeyDown() method. When TAB is pressed, focus is shifted to the next overlay. When ENTER is pressed, it shows a Toast, but that's where you can display your content.
The setFocus() method was found in the documentation for ItemizedOverlay found here: https://developers.google.com/maps/documentation/android/reference/
Hope this works.
public class OverlayFocusExampleActivity extends MapActivity {
private HelloItemizedOverlay itemizedoverlay;
private MapView mapView;
private MapController mapController;
private int currentOverlayIndex;
/*
* This entire method comes from the MapView tutorial.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapController = mapView.getController();
List<Overlay> mapOverlays = mapView.getOverlays();
// overlay_draw is a selector that specifies a different image for state_focused
Drawable drawable = this.getResources().getDrawable(R.drawable.overlay_draw);
itemizedoverlay = new HelloItemizedOverlay(drawable, this);
GeoPoint point = new GeoPoint(19240000, -99120000);
OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!");
itemizedoverlay.addOverlay(overlayitem);
GeoPoint point2 = new GeoPoint(35410000, 139460000);
OverlayItem overlayitem2 = new OverlayItem(point2, "Sekai, konichiwa!", "I'm in Japan!");
itemizedoverlay.addOverlay(overlayitem2);
mapOverlays.add(itemizedoverlay);
}
#Override
protected boolean isRouteDisplayed() {
return false;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
OverlayItem overlay;
switch (keyCode) {
case KeyEvent.KEYCODE_TAB:
// Retrieve next overlay
currentOverlayIndex = (currentOverlayIndex + 1) % itemizedoverlay.size();
overlay = itemizedoverlay.getOverlayItem(currentOverlayIndex);
itemizedoverlay.setFocus(overlay);
// Since setFocus() doesn't center the map, we do it ourselves
mapController.animateTo(overlay.getPoint());
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
overlay = itemizedoverlay.getFocus();
if (overlay != null) {
// Perform associated action
// Stub
Toast.makeText(this, overlay.getSnippet(), Toast.LENGTH_SHORT).show();
return true;
}
default:
return false;
}
}
/*
* This entire class comes from the MapView tutorial except getOverlayItem().
*/
private class HelloItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private Context mContext;
public HelloItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
/*
* Not in MapView tutorial. Added for focusability.
*/
public OverlayItem getOverlayItem(int index) {
return mOverlays.get(index);
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
#Override
protected boolean onTap(int index) {
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
}

Map overlay in android app

I am trying to add a pin image to certain places to my map in my android application, but then there is a big semi transparent rectangle that appears over my map, that does not allow me to interact with the main map, I have tried using map overlay or itemized map overlay, but i get the same result, I dont know if this is because of the image, or this is usually what happens when someone adds an overlay to his map.
PS I am using a .png image
If anyone could help me i would be so grateful
thanks
this is the itemized overlay class
private class MirItemizedOverlay extends ItemizedOverlay {
private List<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
public MirItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
public void addOverlayItem(OverlayItem overlayItem) {
mOverlays.add(overlayItem);
populate();
}
public void addOverlayItem(int lat, int lon, String title) {
GeoPoint point = new GeoPoint(lat, lon);
OverlayItem overlayItem = new OverlayItem(point, title, null);
addOverlayItem(overlayItem);
}
}
and this is how I use it in the oncreate method in my map activity
Drawable makerDefault =this.getResources().getDrawable(R.drawable.redcircle);
MirItemizedOverlay itemizedOverlay = new MirItemizedOverlay(makerDefault);
GeoPoint point = new GeoPoint((int) (49.9736518*1E6), (int) (7.114648 *1E6));
OverlayItem overlayItem = new OverlayItem(point, "hotspot1", null);
itemizedOverlay.addOverlayItem((int) (49.9736518*1E6), (int) (7.114648 *1E6), "hotspot1");
You should add your itemizedOverlay to MapView overlays:
MapView mapView = ...;
mapView.getOverlays().add(itemizedOverlay);

using mutliple drawables on a mapview

I have very limited experience with Mapview, Overlay and ItemizedOverlay. I've seen some simple code examples that use one drawable for overlays and itemizedOverlays but I'm unsure how to approach these requirements: I want more than one drawable on my map view (example: a star-icon for the map center and some other icon for other overlay items) but I want one to be unclickable (the star). Should I use both Overlay and ItemizedOverlay to achieve this?
Also, my next problem is a matter of presentation: If I have 500 items to display on a map, what is a practical way of displaying that information? Again, I have little experience developing and using map applications.
I faced the same situation a couple of weeks ago.
You should use one ItemizedOverlay for each different drawable, and then add overlayItems to the ItemizedOverlay.
The most convenient way is to extend ItemizedOverlay, so you can define a marker and a click behavoir for each style you need.
For the second part, for performance concerns, you shouldn't populate your map with all your 500 items once at a time. I used a system that dynamically adds to the map markers that belongs to the displayed scope of map.
Here is the snippet of my ItemizedOverlay that could be useful for both of your questions :
private class MarkerItemized_Overlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public MarkerItemizedOverlay(Drawable marker, Context context) {
super(boundCenterBottom(marker));
mContext = context;
}
public void addOverlay(OverlayItem overlay) {
if (!mOverlays.contains(overlay)) {
mOverlays.add(overlay);
populate();
}
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
#Override
protected boolean onTap(final int index) {
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.setNegativeButton("Annuler",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){}
});
dialog.setPositiveButton("Naviguer",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){ showDirections(mOverlays.get(index).getPoint()); }
});
dialog.setInverseBackgroundForced(true);
dialog.show();
return true;
}
public boolean contains(Store store) {
return mOverlays.contains(store);
}
#Override
public boolean onTouchEvent(MotionEvent e, MapView mapView) {
if (e.getAction() == MotionEvent.ACTION_UP) {
GeoPoint newCenter = mapView.getMapCenter();
int minLat, maxLat, minLng, maxLng;
minLat = mapCenter.getLatitudeE6() - mapView.getLatitudeSpan()/2;
maxLat = mapCenter.getLatitudeE6() + mapView.getLatitudeSpan()/2;
minLng = mapCenter.getLongitudeE6() - mapView.getLongitudeSpan()/2;
maxLng = mapCenter.getLongitudeE6() + mapView.getLongitudeSpan()/2;
if (newCenter.getLatitudeE6() > maxLat ||
newCenter.getLatitudeE6() < minLat ||
newCenter.getLongitudeE6() > maxLng ||
newCenter.getLongitudeE6() < minLng)
{
mapCenter = mapView.getMapCenter();
Location mapCenterLoc = new Location(providerName);
mapCenterLoc.setLatitude(newCenter.getLatitudeE6()/1E6);
mapCenterLoc.setLongitude(newCenter.getLongitudeE6()/1E6);
Store[] newClosestStores = storeDB.getClosestStores(mapCenterLoc);
for (int i = 0; i < newClosestStores.length; i++)
if (! itemizedOverlay.contains(newClosestStores[i]))
setMarker(newClosestStores[i]);
}
}
return super.onTouchEvent(e, mapView);
}
}

Problem with drawing location using a custom Drawable in an Android OverlayItem

This code is using
the Google APIs (level 8).
When I update the OverlayItem to use a custom drawable the Canvas
object seems to draw the pixels in the wrong location. In this
example I'm trying to draw a circle in Louisiana. When viewing the
entire map the circle is drawn off the map. As you zoom into New
Orleans you'll see the circle approach the appropriate latitude and
longitude. The hot spot seems to be in the correct location, no
matter where the circle is being drawn.
If, in the draw method, the canvas restore method is called the circle
draws in the correct location.
Also If the custom drawable is not used, the icon is drawn in the
correct location (without using Canvas "restore").
Below is the code showing this behavior. I tried adding "setBounds"
and "boundCenterBottom", since other people seemed to indicate that
resolved their "wrong location" problems. Though
to be honest I'm not sure why those calls are needed.
=======================================================================
public class MapsActivity extends MapActivity
{
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
// Itemized Overlay
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable defaultIcon =
this.getResources().getDrawable(R.drawable.icon);
MyItemizedOverlay itemizedoverlay = new
MyItemizedOverlay(defaultIcon, this);
// Overlay Item
GeoPoint pt = new GeoPoint(30000000, -90000000);
OverlayItem item = new OverlayItem(pt,"New Orleans",
"Louisiana");
// Custom Drawable
CustomDrawable customDrawable = new CustomDrawable(pt,
mapView);
boolean showProblem = true;
if (showProblem)
{
item.setMarker(customDrawable);
}
else
{
item.setMarker(defaultIcon);
}
// Add item we want to overlay
itemizedoverlay.addOverlay(item);
// Add overlay
mapOverlays.add(itemizedoverlay);
}
protected boolean isRouteDisplayed()
{
return false;
}
}
=======================================================================
public class MyItemizedOverlay extends ItemizedOverlay<OverlayItem>
{
private ArrayList<OverlayItem> mOverlays = new
ArrayList<OverlayItem>();
private Context mContext;
public MyItemizedOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem item)
{
mOverlays.add(item);
populate();
}
public void removeOverlay(OverlayItem item)
{
mOverlays.remove(item);
}
public void removeOverlay(int item)
{
mOverlays.remove(item);
}
protected OverlayItem createItem(int i)
{
OverlayItem item = mOverlays.get(i);
Drawable drawable = item.getMarker(0);
if (drawable != null)
{
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, w, h);
item.setMarker(boundCenterBottom(drawable));
}
return item;
}
public void draw(android.graphics.Canvas canvas, MapView mapView,
boolean shadow)
{
if (shadow)
return;
super.draw(canvas, mapView, shadow);
}
public int size()
{
return mOverlays.size();
}
protected boolean onTap(int index)
{
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new
AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
=======================================================================
public class CustomDrawable extends ShapeDrawable
{
private int radius = 10;
private GeoPoint point = null;
private MapView mapView = null;
public CustomDrawable(GeoPoint point, MapView mapView)
{
this.point = point;
this.mapView = mapView;
}
public void draw(Canvas canvas)
{
// TODO This (somewhat) fixes projection problem?
//canvas.restore();
Projection projection = mapView.getProjection();
Point pt = projection.toPixels(point, null);
canvas.drawCircle(pt.x, pt.y, radius,
getPaint());
}
public int getIntrinsicHeight()
{
return 2 * radius;
}
public int getIntrinsicWidth()
{
return 2 * radius;
}
}
=======================================================================
Your CustomDrawable shouldn't be positioning itself with respect to the map. It should just draw itself within its bounds, and not reference the MapView or its Projection. ItemizedOverlay takes care of positioning the Drawable for your OverlayItem.

Categories

Resources