Android Google Maps onTap is not called - android

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.

Related

Android osmdroid overlayItem tap detected with offset

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

How to draw only the markers that are visible on the map?

I want to learn drawing only the overlayitems that are visible on the map, because i'm showing a map with thousands of markers. I know that i must check if the overlayitem is visible with something like this:
private boolean isLocationVisible(location)
{
Rect currentMapBoundsRect = new Rect();
Point currentDevicePosition = new Point();
GeoPoint deviceLocation = new GeoPoint((int) (location.getLatitude() * 1000000.0), (int) (location.getLongitude() * 1000000.0));
mapView.getProjection().toPixels(deviceLocation, currentDevicePosition);
mapView.getDrawingRect(currentMapBoundsRect);
return currentMapBoundsRect.contains(currentDevicePosition.x, currentDevicePosition.y);
}
and then if this method returns true i must draw the overlayitem, and if not, i must not draw it.
The problem is that i can't override onDraw in OverlayItem, so i didn't know how to achieve my needs.
What should i change in my code to draw only the markers that are visible on the map?
This is my ItemizedOverlayClass:
public class mItemizedOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
boolean onTapActivated=false;
private Drawable marker = null;
private BusMap map = null;
boolean comingFromFavoriteNameEdit=false;
public BmItemizedOverlay(Drawable defaultMarker, BusMap map) {
super(boundCenterBottom(defaultMarker));
this.map=map;
this.marker=defaultMarker;
}
public mItemizedOverlay(Drawable defaultMarker, BusMap map, boolean onTapActivated) {
super(boundCenterBottom(defaultMarker));
this.map=map;
this.onTapActivated=onTapActivated;
this.marker=defaultMarker;
}
protected OverlayItem createItem(int i){return mOverlays.get(i);}
public int size() {return mOverlays.size();}
public void clear(){mOverlays.clear();}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
}
public void setOverlays(ArrayList <OverlayItem> overlays) {
mOverlays=overlays;
populate();
}
public void draw(Canvas canvas, MapView mapView, boolean shadow){
if (mapView.getZoomLevel() > 17){
boundCenterBottom(this.marker);
super.draw(canvas, mapView, false);
}
}
}
You should not have to handle this yourself. It is the job of ItemizedOverlay to only dispatch and draw the markers that are currently present inside the bounds of the visible map. What is leading you to believe this is not already occurring?
If you decide that the current Overlay implementation is not satisfactory, you will likely have better luck using your checking method to determine when to add or remove items from the Overlay, rather than attempting to override the draw calls.

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;
}
}
}

Placing shape into MapView in Android

Is there a way to place a shape (drawable or shape of any kind) that occupies a specific area in MapView (lat/lon area) not pixel area . I need that for GeoPoint Clustering purposes
If that is not possible any guidance to do it with projection coordinates would be greatly appreciated. But using the MapView canvas to do this doesn't seem performance-wise since i recycle my Overlay Items all the time and i wish i could take advantage of that too.
Look atItemizedOverlay
I'm culling from my code, so this probably wont' compile out of the box, but should give you enough to figure it out from here...
extended class:
public class MyOverlay extends ItemizedOverlay<OverlayItem>
{
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private Context mContext;
private OverlayItem item;
public MyOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
public void addOverlay(OverlayItem overlay)
{
mOverlays.add(overlay);
}
public void doPopulate()
{
populate();
}
#Override
protected OverlayItem createItem(int i)
{
return mOverlays.get(i);
}
#Override
public int size()
{
return mOverlays.size();
}
}
and then in your activity....
public void addLocations(GeoPoint _center)
{
final GeoPoint center = _center;
mapOverlays = mapView.getOverlays();
Drawable drawable = MyActivity.this.getResources().getDrawable(R.drawable.map_annotation_pin);
itemizedoverlay = new ScoopOverlay(drawable,mContext);
//add as many points as you wish...
itemizedoverlay.addOverlay(
new OverlayItem(new GeoPoint(/*lon lat data here*/));
);
showResults.sendEmptyMessage(0);
}
private Handler showResults = new Handler()
{
#Override
public void handleMessage(Message msg)
{
itemizedoverlay.doPopulate();
mapOverlays.add(itemizedoverlay);
mapView.invalidate();
}
};
So the solution is to draw to the ItemizedOverlay that holds the items.
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
// cycle through all overlays
for (int index = 0; index < mOverlays.size(); index++) {
OverlayItemExtended 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 boxPaint = new Paint();
boxPaint.setColor(android.graphics.Color.WHITE);
boxPaint.setStyle(Paint.Style.FILL);
boxPaint.setAlpha(140);
canvas.drawCircle(ptScreenCoord.X, ptScreenCoord.y,
20, boxPaint);
}
}

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