Now I can show the map and markers that are defined in the program, but I need to add markers to touched location.
I think I know the way to do this, which is:
1 To set something like onTouchEventListener to the MapView;
2 Get the position information from Listener;
3 Set the marker according to the position information.
But I am too new to this to find out how to write code to achieve it, especially the step 1. I mean I don't understand how to use the solution like Add marker on touched location using google map in Android .My problem is more fundamental. I dont know how to set eventListener for my MapView and which eventListener should I use. https://developer.mapquest.com/content/mobile/android/documentation/api/com/mapquest/android/maps/Overlay.OverlayTouchEventListener.html This OverlayTouchEventListener seems to be the one but cant find an useful guide for it.
So could some one tell me how to do this in detail?
Eg.How to set the listener and which listener to choose?
Try this...
1. Create interface MyGeoPointListener.java
public interface MyGeoPointListener {
public void GetGeoPoint(GeoPoint geopoint);
}
2. Create Overlay class:
import com.mapquest.android.maps.ItemizedOverlay;
import com.mapquest.android.maps.OverlayItem;
class DynamicMarkerOverlay extends ItemizedOverlay<OverlayItem> {
private boolean isPinch = false;
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private MyGeoPointListener geoPointListener;
public DynamicMarkerOverlay(Drawable defaultMarker,
MyGeoPointListener geoPointListener) {
super(boundCenterBottom(defaultMarker));
this.geoPointListener = geoPointListener;
}
public void addOverlay(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
#Override
public boolean onTap(GeoPoint geoPoint, MapView map) {
if (isPinch) {
return false;
} else {
if (geoPoint != null) {
if (null != geoPointListener) {
geoPointListener.GetGeoPoint(geoPoint);
}
return true;
} else {
if (null != geoPointListener) {
geoPointListener.GetGeoPoint(null);
}
return false;
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event, MapView mapView) {
int fingers = event.getPointerCount();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isPinch = false; // Touch DOWN, don't know if it's a pinch yet
}
if (event.getAction() == MotionEvent.ACTION_MOVE && fingers == 2) {
isPinch = true; // Two fingers, def a pinch
}
return super.onTouchEvent(event, mapView);
}
}
3. Implement MyGeoPointListener in activity
like,
public class MainActivity extends MapActivity implements MyGeoPointListener {
4. Override MyGeoPointListener:
.....
#Override
public void GetGeoPoint(GeoPoint geopoint) {
if (null != geopoint) {
String msg = "Lat: " + geopoint.getLatitudeE6() / 1E6 + " - "
+ "Lon: " + geopoint.getLongitudeE6() / 1E6;
Toast toast = Toast.makeText(MyLocationMap.this, msg,
Toast.LENGTH_SHORT);
toast.show();
List<Overlay> mapOverlays = myMap.getOverlays();
OverlayItem overlayitem = new OverlayItem(geopoint, "address_name",
"address");
Drawable icon = getResources().getDrawable(
R.drawable.location_marker);
DynamicMarkerOverlay customoverlay = new DynamicMarkerOverlay(icon,
this);
customoverlay.addOverlay(overlayitem);
mapOverlays.add(customoverlay);
myMap.getController().animateTo(geopoint);
}
}
.....
5. In OnCreate()
......
public MapView myMap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_map_layout);
.......
.......
myMap = (MapView) findViewById(R.id.map);
Drawable marker = getResources().getDrawable(R.drawable.ic_launcher);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
myMap.getOverlays().add(new DynamicMarkerOverlay(marker, this));
......
}
6. Result:
Related
I'm trying to make two finger rotation for my offline maps using osmdroid. I'm new to using maps for android. I have a geoTIFF, I'm planning to extract info using NDK and later send it to JAVA. I need to use the geoPoint to align with True North Up using compass as well. How can I proceed, any help?
I did try this:
Android Two finger rotation
example, but no luck, my app was not able to detect any two finger event.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = (MapView)findViewById(R.id.mapview);
//Mapview touch utilities
mapView.setClickable(true);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
//set initial zoom-level, depends on your need
mapView.getController().setZoom(nMyZoom);
//Display Position Overlay
/* Itemized Overlay */
{
/* Create a static ItemizedOverlay showing a some Markers on some cities. */
final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
items.add(new OverlayItem("Fruchthalle", "Kaiserslautern", new GeoPoint(nMyLat, nMyLong)));
/* OnTapListener for the Markers, shows a simple Toast. */
this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Toast.makeText(
MainActivity.this,
"Place '" + item.getTitle()+ "' (index=" + index
+ ") got single tapped up", Toast.LENGTH_LONG).show();
return true; // We 'handled' this event.
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
Toast.makeText(
MainActivity.this,
"Place '" + item.getTitle() + "' (index=" + index
+ ") got long pressed", Toast.LENGTH_LONG).show();
return false;
}
}, mResourceProxy);
this.mapView.getOverlays().add(this.mMyLocationOverlay);
}
Have you taken a look at the OpenStreetMapViewer sample app? There is the RotationGestureOverlay overlay in there that specifically shows how to do this. It isn't as smooth as I would like it, but it will do the job.
For simplicity, use the following classes:
public class RotationGestureDetector {
public interface RotationListener {
public void onRotate(float deltaAngle);
}
protected float mRotation;
private RotationListener mListener;
public RotationGestureDetector(RotationListener listener) {
mListener = listener;
}
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
public void onTouch(MotionEvent e) {
if (e.getPointerCount() != 2)
return;
if (e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
mRotation = rotation(e);
}
float rotation = rotation(e);
float delta = rotation - mRotation;
mRotation += delta;
mListener.onRotate(delta);
}
}
And
public class RotationGestureOverlay extends Overlay implements RotationGestureDetector.RotationListener
{
private final RotationGestureDetector mRotationDetector;
private RotationGestureDetector.RotationListener rotationListener;
public RotationGestureOverlay(Context context, RotationGestureDetector.RotationListener rotationListener)
{
super(context);
this.rotationListener = rotationListener;
mRotationDetector = new RotationGestureDetector(this);
}
#Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
if (this.isEnabled()) {
mRotationDetector.onTouch(event);
}
return super.onTouchEvent(event, mapView);
}
#Override
public void onRotate(float deltaAngle)
{
rotationListener.onRotate(deltaAngle);
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean b) {
}
}
Add the overlay:
mapView.getOverlays().add(new RotationGestureOverlay(context,this);
There is already an overlay, drawing something on a map view. I want to add another overlay and a customized item to the map view. Nothing shows. What's wrong with my code? Thanks heaps.
My sub-class of ItemizedOverlay
public class PinItemizedOverlay extends ItemizedOverlay {
private static int MAX_PIN = 3;
private OverlayItem overlays[] = new OverlayItem[MAX_PIN];
private int index = 0;
private boolean full = false;
private Context context;
public PinItemizedOverlay(Context context, Drawable defaultMarker) {
//super(boundCenterBottom(defaultMarker));
super(boundCenterBottom(defaultMarker));
this.context = context;
}
#Override
public OverlayItem createItem(int index) {
return overlays[index];
}
public int size(){
if (full) {
return overlays.length;
} else {
return index;
}
}
public void addOverlay(OverlayItem overlay) {
if (index < MAX_PIN) {
overlays[index] = overlay;
} else {
return;
}
index++;
populate();
}
}
My customized overlay item
public class LocationPinItem extends OverlayItem{
public LocationEntity location;
public LocationPinItem(GeoPoint point, int iconRes, LocationEntity location){
//super(point,null,null);
super(point, null, null);
Drawable marker = getApplicationContext().getResources().getDrawable(iconRes);
super.setMarker(marker );
this.location = location;
}
}
And the function where I add the customized item (it's a drop pin):
private void createMarkerAt(LocationEntity location, String extra, int iconRes, boolean clear, boolean animate) {
if(location == null) {
return;
}
GeoPoint point = new GeoPoint((int) (location.latitude * 1E6), (int) (location.longitude * 1E6));
LocationPinItem pinItem = new LocationPinItem(point,R.drawable.ic_swap,location);
PinItemizedOverlay pinOverlay = new PinItemizedOverlay(getApplicationContext(),mMapDrawable) ;
pinOverlay.addOverlay(pinItem);
mMapView.removeAllViews();
mMapView.postInvalidate();
mMapView.getOverlays().add(pinOverlay);
if(animate) {
mMapView.getController().animateTo(location.toGeoPoint());
}
}
never mind, I figured it out: the newly-added overlay occludes the previous overlay
I am a beginner when it comes to working with the Maps API so please bear with me and I know there have been many other posts dealing with the same issue but I am still stuck.
I have been able to place some overlay images onto my map. The only issue I am having now is that I do not know how to make them disappear when I zoom out enough levels as this causes the overlay images to crowd together and overlap - basicaly making them useless at that level. So, any help on how to make them appear (after zoom level 18) would be truly appreciated.
I have tried using a zoom listener and an if statement but it had no change - most likely because I do not know where exactly I need to implement it and/or what other methods are required to enable it. Also, I am not sure on how to implement the draw() method as many others have used this to make it scale and disappear.
Edit:
These are the two classes I have so far which execute successfully (after applying the answer):
The Map.java file:
public class Map extends com.google.android.maps.MapActivity implements
OnOverlayGestureListener {
private boolean mShowOverlays = true;
private MapView mMapView;
MapView mapView;
MapController mapController;
private void setOverlayVisibility() {
boolean showOverlays = mMapView.getZoomLevel() > 18;
if (showOverlays != mShowOverlays) {
mShowOverlays = showOverlays;
for (Overlay overlay : mMapView.getOverlays()) {
if (overlay instanceof ItemOverlay) {
((ItemOverlay) overlay).setVisible(showOverlays);
}
}
}
}
/** Called when the activity is first created. */
#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();
mapController.setZoom(17);
boolean showOverlays = mMapView.getZoomLevel() > 18;
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable lot = this.getResources().getDrawable(R.drawable.lot);
ItemOverlay parking_lot = new ItemOverlay(lot, this);
GeoPoint point1 = new GeoPoint(43806622, -79219797);
OverlayItem parking = new OverlayItem(point1, "Shopping Center","Parking Lot");
parking_lot.addOverlayItems(parking);
mapOverlays.add(parking_lot);
Drawable logo = this.getResources().getDrawable(R.drawable.entrance);
ItemOverlay ent = new ItemOverlay(logo, this);
GeoPoint start = new GeoPoint(43805697, -79221031);
mapController.setCenter(start);
OverlayItem welcome = new OverlayItem(start, "Welcome", " ");
ent.addOverlayItems(welcome);
mapOverlays.add(ent);
public <ZoomEvent> boolean onZoom(ZoomEvent ze, ManagedOverlay mo) {
setOverlayVisibility();
return true;
}
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
The ItemOverlay.java file:
public class ItemOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
private Context mContext;
private boolean visible = true;
private boolean mVisible = true;
public void setVisible(boolean value) {
mVisible = value;
}
public boolean isVisible() {
return mVisible ;
}
#Override
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
if (mVisible) {
super.draw(canvas, mapView, shadow);
}
}
public ItemOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
mContext = context;
}
public void addOverlayItems(OverlayItem overlay) {
mOverlays.add(overlay);
populate();
}
#Override
protected OverlayItem createItem(int i) {
// TODO Auto-generated method stub
return mOverlays.get(i);
}
#Override
public int size() {
// TODO Auto-generated method stub
return mOverlays.size();
}
#Override
protected boolean onTap(int index) {
// TODO Auto-generated method stub
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
}
I really like using the OverlayManager library for Android. It adds features to the Google Maps code, and makes a few things a lot easier. Find it here including some demo code that uses it
Option #1: If you use this, then you can use the OverlayManager's gesture listener interface for your MapActivity, to receive a callback for each zoom (in/out) event.
public class Map extends MapActivity implements OnOverlayGestureListener
{
private boolean mShowOverlays = true;
private MapView mMapView; // assign this in onCreate()
private void setOverlayVisibility() {
boolean showOverlays = mMapView.getZoomLevel() >= 18;
if (showOverlays != mShowOverlays) {
mShowOverlays = showOverlays;
for (Overlay overlay : mMapView.getOverlays()) {
if (overlay instanceof ItemOverlay) {
((ItemOverlay)overlay).setVisible(showOverlays);
}
}
}
}
// this is the onOverlayGestureListener callback:
public boolean onZoom(ZoomEvent ze, ManagedOverlay mo) {
setOverlayVisibility();
return true;
}
}
You will have to also add your Map instance as a gesture listener with ManagedOverlay.setOnOverlayGestureListener(). See the sample code for that.
Finally, in your ItemOverlay class, you can override the draw() method, and selectively draw based on whether the overlay has been marked as visible or not. You need to add a custom visible property:
public class ItemOverlay extends ItemizedOverlay {
private boolean mVisible = true;
public void setVisible(boolean value) {
mVisible = value;
}
public boolean isVisible() {
return mVisible ;
}
#Override
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
if (mVisible) {
super.draw(canvas, mapView, shadow);
}
}
}
Option #2: Now, using the Overlay Manager library just for this one purpose might be overkill. So, another, probably simpler alternative is to create a zoom listener in the way described in this stack overflow answer. The code Kurru provides would go in your Map class. You would replace this in the answer's code:
checkMapIcons();
with the method I showed above:
setOverlayVisibility();
So, now you have two ways to "watch" the zoom level, and overriding ItemOverlay.draw() allows you to make the markers disappear whenever you like (zoom level < 18 in this example).
I can't succeed to put a custom centered overlay item on my map. It always appears centered on bottom and middle. Here is my code:
------------My overlay item class-------------
public class EditionThumbOverlayItem extends OverlayItem {
public EditionThumbOverlayItem(GeoPoint aGeoPoint, Resources resources) {
super("", "", aGeoPoint);
Drawable pinThumbDrawable = resources.getDrawable(R.drawable.pin_thumb);
pinThumbDrawable.setBounds(pinThumbDrawable.getIntrinsicWidth() * (-2 / 5),
pinThumbDrawable.getIntrinsicHeight() * (-2 / 5), pinThumbDrawable.getIntrinsicWidth() * 3 / 5,
pinThumbDrawable.getIntrinsicHeight() * 3 / 5);
setMarker(pinThumbDrawable);
}
}
-------------my itemized overlay class-----------------
public class PinThumbOverlay extends ItemizedOverlay<OverlayItem> {
// Only one item can be set on this overlay
private OverlayItem mEditionThumb;
public PinThumbOverlay(Drawable pDefaultMarker, ResourceProxy pResourceProxy) {
super(pDefaultMarker, pResourceProxy);
}
#Override
public boolean onSnapToItem(int arg0, int arg1, Point arg2, IMapView arg3) {
return false;
}
#Override
protected OverlayItem createItem(int arg0) {
return mEditionThumb;
}
#Override
public int size() {
if (mEditionThumb == null) {
return 0;
} else {
return 1;
}
}
public void addOverlayItem(OverlayItem overlay) {
mEditionThumb = overlay;
populate();
}
public void removeOverlayItem() {
mEditionThumb = null;
populate();
}
}
-----------------itemized overlay creation----------------------
DefaultResourceProxyImpl defaultResouceProxyImpl = new DefaultResourceProxyImpl(getApplicationContext());
Drawable defaultPinEdition = getResources().getDrawable(R.drawable.pin_thumb);
mPinThumbOverlay = new PinThumbOverlay(defaultPinEdition, defaultResouceProxyImpl);
mMapView.getOverlays().clear();
mMapView.getOverlays().add(mPinThumbOverlay);
-------------------Overlay item creation-------------------------
EditionThumbOverlayItem editionThumb = new EditionThumbOverlayItem(new GeoPoint(mCurrentUserLocation),
getResources());
mPinThumbOverlay.addOverlayItem(editionThumb);
As a note: I use osmdroid map, not default google map api.
It seems that osmdroid overwrites any values you set with the drawble.setBounds() method in the onDrawItem method in ItemizedOverlay:
protected void onDrawItem(final Canvas canvas, final Item item, final Point curScreenCoords) {
final int state = (mDrawFocusedItem && (mFocusedItem == item) ? OverlayItem.ITEM_STATE_FOCUSED_MASK
: 0);
final Drawable marker = (item.getMarker(state) == null) ? getDefaultMarker(state) : item
.getMarker(state);
final HotspotPlace hotspot = item.getMarkerHotspot();
boundToHotspot(marker, hotspot);
// draw it
Overlay.drawAt(canvas, marker, curScreenCoords.x, curScreenCoords.y, false);
}
Or rather, the actual overwriting will be done in the boundToHotspot(marker,hotspot); method.
To overcome this set your hotspot on your OverlayItem instead of setting the bounds on the drawable.
Example:
GeoPoint point = new GeoPoint(currentLoc);
OverlayItem item = new OverlayItem("my location", "my loc", point);
item.setMarkerHotspot(HotspotPlace.BOTTOM_CENTER);
This should produce the result your looking for.
If you just want to put a marker in the map center, use this code snippet:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
mapView.setClickable(true);
mapView.setUseDataConnection(true);
mapView.getController().setZoom(MAP_DEFAULT_ZOOM);
mapView.setTileSource(TileSourceFactory.MAPNIK);
resourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
GeoPoint location = getLocation()
ItemizedIconOverlay<OverlayItem> currentLocationOverlay;
Drawable marker = this.getResources().getDrawable(R.drawable.custom_marker);
OverlayItem myLocationOverlayItem = new OverlayItem("Here", "Current Position", location);
myLocationOverlayItem.setMarker(marker);
final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
items.add(myLocationOverlayItem);
currentLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
return true;
}
public boolean onItemLongPress(final int index, final OverlayItem item) {
return true;
}
}, resourceProxy);
mapView.getOverlays().add(this.currentLocationOverlay);
mapView.getController().setCenter(location);
}
Is there any way to put a pushpin on an android map and when it's touched displays a popup with some extra info?
You need to extend this http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/ItemizedOverlay.html.
public class CustomOverlay extends ItemizedOverlay<OverlayItem> {
private Context context;
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
public CustomOverlay(Drawable defaultMarker, Context context) {
super(boundCenterBottom(defaultMarker));
this.context = context;
//after adding things to the overlay, call these:
setLastFocusedIndex(-1);
populate();
}
#Override
protected boolean onTap(int index) {
//called when an item is tapped
return true;
}
#Override
public boolean onTap (final GeoPoint p, final MapView mapV) {
boolean tapped = super.onTap(p, mapV);
if(!tapped){
//you can use this to check for other taps on the custom elements you are drawing
}
return true;
}
#Override
public void draw(Canvas canvas, MapView mapV, boolean shadow){
if(!shadow)
// if you have a custom image you may not want the shadow to be drawn
super.draw(canvas,mapV,shadow);
if(selected != null) {
// selected just means that something was clicked
// it isn't defined in this example
Projection projection = mapV.getProjection();
Point drawPoint = projection.toPixels(selected.getPoint(), null);
//get coordinates so you can do your drawing code afterward
}
}
#Override
protected OverlayItem createItem(int i) {
return mOverlays.get(i);
}
#Override
public int size() {
return mOverlays.size();
}
}
This is a very rough sketch of what you need to do. Hope this helps.