How do I long click on a mapview so that a place marker appears at that point on the map?
I tried a couple ways without success:
1) Using setOnLongCl
ambrose,
I modified the demo of the library mapview-overlay-manager. to get this code running with a double tap gesture:
package de.android1.overlaymanager.demo;
import android.os.Bundle;
import android.widget.Toast;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MapController;
import com.google.android.maps.GeoPoint;
import de.android1.overlaymanager.*;
public class DemoView extends MapActivity {
MapView mapView;
MapController mapController;
OverlayManager overlayManager;
@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();
overlayManager = new OverlayManager(getApplication(), mapView);
}
@Override
public void onWindowFocusChanged(boolean b) {
createOverlayWithListener();
}
public void createOverlayWithListener() {
//This time we use our own marker
final ManagedOverlay managedOverlay = overlayManager.createOverlay("listenerOverlay", getResources().getDrawable(R.drawable.marker));
for (int i = 0; i < 40; i = i + 3) {
managedOverlay.createItem(GeoHelper.geopoint[i], "Item" + i);
}
managedOverlay.setOnOverlayGestureListener(new ManagedOverlayGestureDetector.OnOverlayGestureListener() {
public boolean onZoom(ZoomEvent zoom, ManagedOverlay overlay) {
return false;
}
public boolean onDoubleTap(MotionEvent e, ManagedOverlay overlay, GeoPoint point, ManagedOverlayItem item) {
Drawable defaultmarker = getResources().getDrawable(R.drawable.marker);
ManagedOverlay managedOverlay = overlayManager.createOverlay(defaultmarker);
//creating some marker:
managedOverlay.createItem(point);
//registers the ManagedOverlayer to the MapView
overlayManager.populate();
Toast.makeText(getApplicationContext(), "You created a Marker!", Toast.LENGTH_LONG).show();
return true;
}
public void onLongPress(MotionEvent arg0, ManagedOverlay arg1) {
// TODO Auto-generated method stub
}
public void onLongPressFinished(MotionEvent arg0,
ManagedOverlay arg1, GeoPoint arg2, ManagedOverlayItem arg3) {
// TODO Auto-generated method stub
}
public boolean onScrolled(MotionEvent arg0, MotionEvent arg1,
float arg2, float arg3, ManagedOverlay arg4) {
// TODO Auto-generated method stub
return false;
}
public boolean onSingleTap(MotionEvent arg0, ManagedOverlay arg1,
GeoPoint arg2, ManagedOverlayItem arg3) {
// TODO Auto-generated method stub
return false;
}
});
overlayManager.populate();
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
}
Hope it helps.
This mapview-overlay-manager library is super. The reason onLongPress gets triggered when 'scrolling' is because the library does not take into account multitouch. You can work around this by rejecting onLongPress if there is more than one pointer involved as so:
public void onLongPress(MotionEvent motionEvent, ManagedOverlay arg1) {
if (motionEvent.getPointerCount() > 1) return;
... your logic here ...
}
If you're going with the delayed post/message to a handler (a solution I use myself), it can be useful to test if the map has moved, i.e. if mapView.getMapCenter()
, mapView.getLatitudeSpan()
and mapView.getLongitudeSpan()
return the same as when the pointer went down.
I also got a ClassCastException when I tried using MyMapView. As a workaround, I created a MyMapView object instead of a MapView object and programmatically added it to the layout, and that worked great.
MyMapView mapView = new MyMapView(this, this.getString(R.string.APIMapKey));
mapView.displayZoomControls(false);
mapView.setClickable(true);
FrameLayout item = (FrameLayout) findViewById(R.id.getlocationmap);
item.addView((MapView)mapView);
Best way I know to do this is to use the open source mapview-overlay-manager and use its gesture listener which provides a callback for
public void onLongPress(MotionEvent e, ManagedOverlay overlay)
I've found an even easier way. Just make an overlay as the first overlay in the list that does not draw anything and use it to recognize gestures using the GestureDetector. It should then return true if it handled the event so it doesn't get propagated.
List<Overlay> overlays = mapView.getOverlays();
overlays.clear();
overlays.add(new MapGestureDetectorOverlay(new MyOnGestureListener()));
And here's the class:
public class MapGestureDetectorOverlay extends Overlay implements OnGestureListener {
private GestureDetector gestureDetector;
private OnGestureListener onGestureListener;
public MapGestureDetectorOverlay() {
gestureDetector = new GestureDetector(this);
}
public MapGestureDetectorOverlay(OnGestureListener onGestureListener) {
this();
setOnGestureListener(onGestureListener);
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
if (onGestureListener != null) {
return onGestureListener.onDown(e);
}
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (onGestureListener != null) {
return onGestureListener.onFling(e1, e2, velocityX, velocityY);
}
return false;
}
@Override
public void onLongPress(MotionEvent e) {
if (onGestureListener != null) {
onGestureListener.onLongPress(e);
}
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
if (onGestureListener != null) {
onGestureListener.onScroll(e1, e2, distanceX, distanceY);
}
return false;
}
@Override
public void onShowPress(MotionEvent e) {
if (onGestureListener != null) {
onGestureListener.onShowPress(e);
}
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (onGestureListener != null) {
onGestureListener.onSingleTapUp(e);
}
return false;
}
public boolean isLongpressEnabled() {
return gestureDetector.isLongpressEnabled();
}
public void setIsLongpressEnabled(boolean isLongpressEnabled) {
gestureDetector.setIsLongpressEnabled(isLongpressEnabled);
}
public OnGestureListener getOnGestureListener() {
return onGestureListener;
}
public void setOnGestureListener(OnGestureListener onGestureListener) {
this.onGestureListener = onGestureListener;
}
}