I am trying to add the marker dynamically (not static). Dynamically meaning, adding markers as and when I get updates from server.
So, following is my code for ItemizedOverlay:
private class VehicleItemizedOverlay extends ItemizedOverlay<OverlayItem>{
private ArrayList<OverlayItem> mOverlayItems = new ArrayList<OverlayItem>();
public VehicleItemizedOverlay(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 pos) {
return mOverlayItems.get(pos);
}
#Override
public int size() {
if(mOverlayItems!=null) return mOverlayItems.size();
else return 0;
}
public void addOverlayItem(double longitude, double latitude, Bitmap bitmap){
if(Preferences.DEBUG) Log.d("MapActivity", "Latitude: "+latitude+" Longitude: "+longitude);
MarkerDrawable drawable = new MarkerDrawable(MapActivity.this, bitmap);
OverlayItem item = new OverlayItem("a", "a", new GeoPoint((int)(latitude*1e6), (int)(longitude*1e6)));
item.setMarker(drawable);
item.setMarkerHotspot(HotspotPlace.CENTER);
mOverlayItems.add(item);
populateNow();
}
public void populateNow(){
populate();
}
}
Following is the way, I am creating ItemizedOverlay & adding it to MapView in my activity onCreate():
mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());
mVehicleOverlay = new VehicleItemizedOverlay(getResources().getDrawable(R.drawable.stub), mResourceProxy);
mMapView.getOverlays().add(mOverlay);
Now, whenever I get response from server, I am creating & adding overlayItems to ItemizedOverlay.
//onResponse is callback I received on receiving response. Vehicle is my vehicle object
public void onResponse(ArrayList<Vehicle> aVehicles) {
for(int i=0;i<mVehicles.size();i++){
final int lat = (int)(mVehicles.get(i).getLatitude()*1e6);
final int lon = (int)(mVehicles.get(i).getLongitude()*1e6);
mVehicleOverlay.addOverlayItem(lon, lat, bitmap);
}
}
But all overlay items are overlapped over each other at center point of the map. Am I missing anything?
Also, if I add some static overlay items to mVehicleOverlay before adding it then it work properly.
mVehicleOverlay = new VehicleItemizedOverlay(getResources().getDrawable(R.drawable.stub), mResourceProxy);
final int lat = (int)(STATIC_LATITUDE*1e6);
final int lat = (int)(STATIC_LONGITUDE*1e6);
mOverlay.addOverlayItem(lon, lat, bitmap);
mMapView.getOverlays().add(mVehicleOverlay);
In OSMDroid, after adding custom itemized overlay, should I not add & populate overlayItems to it like we do in case of Google API v1? Or I am missing anything here?
Related
Without using the ClusterManager, I use HashMap to put the Marker and ID into the HashMap, and get the ID in the OnMarkClick method and get the data from database. It's works
markers.put(addNewMarker(geoPoint), objectId);
private Marker addNewMarker(ParseGeoPoint parseGeoPoint) {
double latitude = parseGeoPoint.getLatitude();
double longitude = parseGeoPoint.getLongitude();
return googleMap.addMarker(new MarkerOptions().position(
new LatLng(latitude, longitude)));
}
#Override
public boolean onMarkerClick(Marker marker) {
String objectId = markers.get(marker);
if (null == objectId) {
return false;
}
getMemoryBriefInfo(objectId);
return true;
}
But now I need to use the ClusterManager to cluster multiple markers into number.
The problems is It seems there is no way to implement this, in the demo of Google, it just add the Items into the Cluster.
There is a OnMarkerClick method in the ClusterManager class, but I don't how to Override this and set with my own unique ID.
there is a global solution for you that help to add title, snippet and icon so you can get what you want.
Modify your ClusterItem Object and add 3 variables :
public class MyItem implements ClusterItem {
private final LatLng mPosition;
BitmapDescriptor icon;
String title;
String snippet;
public MyItem(BitmapDescriptor ic,Double lat , Double lng,String tit ,String sni)
{
mPosition = new LatLng(lat,lng);
icon = ic;
title = tit;
snippet = sni;
}
And after you create your costume render :
public class OwnRendring extends DefaultClusterRenderer<MyItem> {
public OwnRendring(Context context, GoogleMap map,
ClusterManager<MyItem> clusterManager) {
super(context, map, clusterManager);
}
protected void onBeforeClusterItemRendered(MyItem item, MarkerOptions markerOptions) {
markerOptions.icon(item.getIcon());
markerOptions.snippet(item.getSnippet());
markerOptions.title(item.getTitle());
super.onBeforeClusterItemRendered(item, markerOptions);
}
}
After that just put this line in your SetUpCluster() function before addItems():
mClusterManager.setRenderer(new OwnRendring(getApplicationContext(),mMap,mClusterManager));
I'm trying to create an application that uses OSMDroid and mapoverlays with geoPoints from the xml file, but i have a problem. Code editor doesn't show me an error or warning but when i run the application in emulator it shows that application has stopped working.
This the code of mapActivity:
public class MapsActivity extends Activity implements LocationListener, MapViewConstants {
private MapView mapView;
private MapController mapController;
private LocationManager mLocMgr;
static final String URL = "data/data/com.siroki.brijeg/data.xml";
// XML node keys
static final String KEY_ITEM = "object"; // parent node
static final String KEY_ID = "id";
static final String KEY_NAME = "name";
static final String KEY_LON = "lon";
static final String KEY_LAT = "lat";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.copymain);
mapView = (MapView) this.findViewById(R.id.mapview);
mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setBuiltInZoomControls(true);
mapView.setMultiTouchControls(true);
mapController = this.mapView.getController();
mapController.setZoom(14);
GeoPoint point2 = new GeoPoint(43.3803, 17.5981);
mapController.setCenter(point2);
mLocMgr = (LocationManager) getSystemService(LOCATION_SERVICE);
mLocMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 100, this);
mapView.invalidate();
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable marker = this.getResources().getDrawable(R.drawable.ic_launcher);
ObjectsOverlay itemizedOverlay = new ObjectsOverlay(marker, null);
ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL);
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
// looping through all item nodes <item>
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_ID, parser.getValue(e, KEY_ID));
map.put(KEY_NAME, parser.getValue(e, KEY_NAME));
map.put(KEY_LON, "Rs." + parser.getValue(e, KEY_LON));
map.put(KEY_LAT, parser.getValue(e, KEY_LAT));
// adding HashList to ArrayList
menuItems.add(map);
GeoPoint geo = new GeoPoint(Double.parseDouble(parser.getValue(e, KEY_LAT)), Double.parseDouble(parser.getValue(e, KEY_LON)));
OverlayItem overlayitem = new OverlayItem("Hellow", "World", geo);
itemizedOverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedOverlay);
}
}
public void onLocationChanged(Location location) {
double lat = 43.3803;
double lng = 17.5981 ;
GeoPoint gpt = new GeoPoint(lat, lng);
mapController.setCenter(gpt);
mapView.invalidate();
}
#Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
ObjectsOverlay.java :
public class ObjectsOverlay extends ItemizedOverlay<OverlayItem> {
public ObjectsOverlay(Drawable pDefaultMarker, ResourceProxy pResourceProxy) {
super(pDefaultMarker, pResourceProxy);
// TODO Auto-generated constructor stub
}
private ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>();
private Context context;
#Override
protected OverlayItem createItem(int i) {
return mapOverlays.get(i);
}
#Override
public int size() {
return mapOverlays.size();
}
protected boolean onTap(int index) {
OverlayItem item = mapOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
public void addOverlay(OverlayItem overlay) {
mapOverlays.add(overlay);
this.populate();
}
#Override
public boolean onSnapToItem(int arg0, int arg1, Point arg2, IMapView arg3) {
// TODO Auto-generated method stub
return false;
}
}
And XML file data.xml:
<?xml version="1.0" encoding="UTF-8"?>
<objects>
<object>
<id>1</id>
<name>Siroki</name>
<lon>17.602985</lon>
<lat>43.374276</lat>
</object>
</objects>
I didn't wrote the imports code becouse they take alot of space. :D
First, the context defined in your ObjectsOverlay is never being set. You should add a Context parameter in the constructor:
public ObjectsOverlay(Drawable pDefaultMarker, ResourceProxy pResourceProxy, Context context) {
super(pDefaultMarker, pResourceProxy);
this.context = context;
}
so that the DialogBuilder used in onTap can have a context to create the dialog on. Without this your app will most probably crash when tapping an item.
Next, you wrongly initialized the GeoPoint, it should be done like this:
GeoPoint point = new GeoPoint(19240000,-99120000);
OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!", "I'm in Mexico City!");
GeoPoint coordinates are not double, like Location coordinates. They are int equal to coordinate * 1E6. Use it like this:
int lon = (int)Math.round(lon_as_double*1E6)
And the last thing, you do
itemizedOverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedOverlay);
in the same for-loop. But you should actually just addOverlay in the loop, where you add one by one object by its coordinates, and add the complete itemizedOverlay to the map after the loop.
Oh and you could also add the overlay at the beginning (before the loop), and then populate it using addOverlay. The order does not matter, it only matters to add the overlay once with mapOverlays.add.
Fix that and see if errors still happen.
Regards.
I've been following the NooYawk MapView example with reasonable success. I've replaced the hardcoded geopoints and descriptions based on some system update messages. New markers are added just fine when a new update occurs. The problem is the markers don't go away when the problem is resolved.
I'd be happy enough to remove all markers on press of the refresh button as they get added back in.
Any ideas?
The below is somewhat sanitized.
private class SitesOverlay extends ItemizedOverlay<OverlayItem> {
private List<OverlayItem> items=new ArrayList<OverlayItem>();
private Drawable marker=null;
public SitesOverlay(Drawable marker) {
super(marker);
this.marker=marker;
try {
data = getData();
} catch (MalformedURLException e) {
//
}
if (!data.equals("")) {
// process data
for (Integer i = 0; i < outages.length; i++) {
items.add(new OverlayItem(
getPoint(lat, lng, headerMsg, bodyMsg));
}
}
populate();
}
#Override
protected OverlayItem createItem(int i) {
return(items.get(i));
}
#Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
super.draw(canvas, mapView, false);
boundCenterBottom(marker);
}
#Override
protected boolean onTap(int i) {
Toast.makeText(getBaseContext(),
items.get(i).getSnippet(),
Toast.LENGTH_LONG).show();
return(true);
}
#Override
public int size() {
return(items.size());
}
}
on Refresh Button click mapview.getOverlays().clear(); Then start push pin in map and after adding Overlays you should mapview.postinvalidate()
On my application i receive coordinates from a remote server and i want to mark the location on the coordinates on a map, this happens on demand inside onClick method. The problem is that when i update the location i end up with multiple markers on the map instead of just one, the current location. is there any way to remove the previous marker before adding the next one?
I followed the steps in this tutorial : http://developer.android.com/resources/tutorials/views/hello-mapview.html
And my code goes like this :
public class AppTwoAndroid extends MapActivity {
private Button refreshButton;
double lat, lon;
ConnectionHandler conhandler;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
Log.i("AppTwo", "making connectionhandler object");
conhandler = new ConnectionHandler();
conhandler.execute();
Log.i("AppTwo", "making button");
this.refreshButton = (Button)this.findViewById(R.id.close);
final List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.androidmarker);
final AppTwoAndroidItemizedOverlay itemizedoverlay = new AppTwoAndroidItemizedOverlay(drawable);
refreshButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("AppTwo", "inside onclick");
if (mapOverlays.contains(itemizedoverlay) == true) {
mapOverlays.remove(itemizedoverlay);
}
conhandler.write();
lat = conhandler.retLat();
lon = conhandler.retLon();
lat = lat * 1e6;
lon = lon * 1e6;
int ilat = (int) lat;
int ilon = (int) lon;
GeoPoint point = new GeoPoint(ilat ,ilon);
OverlayItem overlayitem = new OverlayItem(point, null, "AppOne");
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
Toast.makeText(getBaseContext(), "lat is: " + lat + " lon is: " + lon
, Toast.LENGTH_SHORT).show();
}
});
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
and my AppTwoAndroidItemizedOverlay class is :
public class AppTwoAndroidItemizedOverlay extends ItemizedOverlay {
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public AppTwoAndroidItemizedOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
// TODO Auto-generated constructor stub
}
#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;
}
public AppTwoAndroidItemizedOverlay(Drawable defaultMarker, Context context) {
super(defaultMarker);
mContext = context;
}
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();
}
}
In the onClick method just give
mapOverlays.clear();
this should clear any existing markers.
Hope this works :)
In this part of code:
if (mapOverlays.contains(itemizedoverlay) == true) {
mapOverlays.remove(itemizedoverlay);
}
When your removing the Overlay from the mapOverlay structure you are not really clearing the overlay, so when you add other item and re-add it to the mapOverlay there will be 2 markers.
If you just want a single marker do an Overlay that has setOverlayItem instead of a list with an 'adding' logic. (meaning do a overlay with just an item that when you add another, just replaces the old one)
Hope it helped! :D
Add this statement before the code....
mMap.clear();
mMap.clear();
LatLng latLng = new LatLng(gps.getLatitude(), gps.getLongitude());
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new
LatLng(gps.getLatitude(), gps.getLongitude()), 15));
mMap.addMarker(new MarkerOptions().position(latLng).title(""));
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
I have the following code and the markers are not appearing on the map at all!
private class SitesOverlay extends ItemizedOverlay<pfOverlayItem> {
private List<pfOverlayItem> items=new ArrayList<pfOverlayItem>();
//private PopupPanel panel=new PopupPanel(R.layout.popup);
public SitesOverlay() {
super(null);
items = mainOverlayArray;
populate();
}
#Override
protected pfOverlayItem createItem(int i) {
return(items.get(i));
}
#Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow) {
super.draw(canvas, mapView, shadow);
}
#Override
public int size() {
return(items.size());
}
private Drawable getMarker(int resource) {
Drawable marker=getResources().getDrawable(resource);
marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight());
boundCenter(marker);
return(marker);
}
}
mainOverlayArray is full of pfOverlayItem's and the code for that class is
public class pfOverlayItem extends OverlayItem {
private String coolText;
public String getcoolText() {
return coolText;
}
public void setcoolText(String coolText) {
this.coolText = coolText;
}
public pfOverlayItem(GeoPoint point, String title, String snippet) {
super(point, title, snippet);
// TODO Auto-generated constructor stub
}
}
I also set the marker outside of this after processing an XML file...
ArrayList<pfOverlayItem> overArray = myXMLHandler.getOverlayArray();
mainOverlayArray = overArray;
pfOverlayItem tempOver = null;
Drawable marker = getResources().getDrawable(R.drawable.icon);
for (int i = 0; i < mainOverlayArray.size(); i++) {
tempOver = mainOverlayArray.get(i);
tempOver.setMarker(marker);
}
sites=new SitesOverlay();
myMapView.getOverlays().add(sites);
myMapView.invalidate(); [/code]
It looks as though you're starting from one of my many sample Google Map applications. Your code as shown here is incomplete (e.g., according to the code here, you never create any OverlayItem instances).
My recommendation is you roll back to one of the samples I link to above and start modifying from there, or you start trying to figure out which of your methods are getting called and which are not.