4

I'm using android maps utils for clustering the markers on google maps api v2. It worked fine, but when I added 2000+ markers, on max zoom it is still clustered (markers still have numbers):

2000+ markers max zoom

Here is my method for filling map with markers:

public void getRiverData(String state, String type) {
    URL = getResources().getString(R.string.base_url) + state + "/" + type
            + getResources().getString(R.string.end_url);
    SimpleXmlRequest<XMLData> simpleRequest = new SimpleXmlRequest<XMLData>(
            URL, XMLData.class, new Response.Listener<XMLData>() {

                @Override
                public void onResponse(XMLData response) {

                    // Initialize the manager with the context and the map.
                    // (Activity extends context, so we can pass 'this' in
                    // the constructor.)
                    mClusterManager = new ClusterManager<MarkerItem>(
                            getActivity(), map);

                    mClusterManager.setRenderer(new ClusterRenderer(
                            getActivity(), map, mClusterManager));

                    // response Object
                    waterItemsList = response.getNews();

                    for (News item : waterItemsList) {
                        if (item.getRiver_name() != null
                                && item.getRiver_name() != "") {

                            water_level_value = item.getWater_level_value();

                            if (water_level_value != null
                                    && !water_level_value.equals(0)
                                    && !water_level_value.equals("")) {

                                MarkerItem offsetItem = new MarkerItem(item);
                                mClusterManager.addItem(offsetItem);

                            }

                            map.setOnMarkerClickListener(mClusterManager);

                            map.setInfoWindowAdapter(new InfoWindowAdapter() {

                                @Override
                                public View getInfoWindow(Marker marker) {

                                    return null;
                                }

                                @Override
                                public View getInfoContents(Marker marker) {

                                    try {
                                        View v = getActivity()
                                                .getLayoutInflater()
                                                .inflate(
                                                        R.layout.marker_info,
                                                        null);
                                        TextView title = (TextView) v
                                                .findViewById(R.id.tvMarkerTitle);
                                        TextView info = (TextView) v
                                                .findViewById(R.id.tvMarkerInfo);

                                        title.setText(marker.getTitle()
                                                .toString());
                                        info.setText(marker.getSnippet()
                                                .toString());
                                        return v;
                                    } catch (Exception e) {
                                        // kliknięcie w cluster
                                        return null;

                                    }

                                }
                            });

                        }

                    }

                    map.setOnCameraChangeListener(mClusterManager);

                    map.setOnInfoWindowClickListener(mClusterManager);

                    mClusterManager.cluster();

                }

            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // error Object
                    error.printStackTrace();
                }
            });

    AppController.getInstance().addToRequestQueue(simpleRequest);
}

Can anyone help me? Why is it not working?

Kailas
  • 7,350
  • 3
  • 47
  • 63
dudeck
  • 393
  • 5
  • 13
  • 2
    i think this happens due to (7) marker with same position. – Haresh Chhelana Jun 11 '14 at 09:34
  • It could be. Is any method to check if marker with the same position exists? – dudeck Jun 11 '14 at 09:42
  • 1
    Just do it on purpose: give your map 7 markers with exact same position to test how it behaves. And give it 7 markers with slightly different positions (+/- 0.0001 lat/lon) to see if it works. – Vincent Mimoun-Prat Jun 11 '14 at 09:47
  • @dudeck "the same position" means the same coords, so you can easily check yourself. – Marcin Orlowski Jun 11 '14 at 09:49
  • it is not ri8 solution yet we have to find some other solution for this!!! – Haresh Chhelana Jun 11 '14 at 09:49
  • @Marcin Orlowski Yes, I know what it's mean, but I need to check if I have added a marker on this position. And I don't now what is the best solution to check that. I can make for each loop and another List to check if langitutde or longitude of marker have been added to list, but I don't know if it is effective way – dudeck Jun 11 '14 at 10:57
  • @MarvinLabs I did like you said and know it is working. So thanks for all of you for finding the reason and now please answer what is the best way to filter this markers for one marker on one position (cords). – dudeck Jun 11 '14 at 11:14
  • Ok I add sth like that: if (item.getLatitude().equals( addedItem.getLatitude()) || (item.getLongitude() .equals(addedItem .getLongitude()))) { markerExists = true; } } if (!markerExists) { addedItemsList.add(item); and it works :) – dudeck Jun 11 '14 at 11:50

3 Answers3

15

You can extend DefaultClusterRenderer class and set minimum markers to cluster.

public class InfoMarkerRenderer extends DefaultClusterRenderer<MyCustomMarker> {

public InfoMarkerRenderer(Context context, GoogleMap map, ClusterManager<MyCustomMarker> clusterManager) {
    super(context, map, clusterManager);
    //constructor
}

@Override
protected void onBeforeClusterItemRendered(final MyCustomMarker infomarker, MarkerOptions markerOptions) {
      // you can change marker options
}

@Override
protected boolean shouldRenderAsCluster(Cluster cluster) {
    return cluster.getSize() > 5; // if markers <=5 then not clustering
}
}
buxik
  • 2,583
  • 24
  • 31
  • This approach works great. You can use more sophisticated tests to determine whether to cluster or not as well. – rfay Nov 07 '14 at 00:08
3

Via trail and error I found that if the markers are within ~10 feet (equivalent to 0.0000350º difference in lat or long), the markers don't decluster even at the max zoom level.

One way to solve for this problem is to implement a custom Renderer and let the app decide when to cluster. For example, the below code will cluster only when there are more than 1 marker and not at max Zoom. In other words it will decluster all markers at max zoom.

mClusterManager.setRenderer(new DefaultClusterRenderer<MyItem>(mContext, googleMap, mClusterManager) {
    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        if(cluster.getSize() > 1 && mCurrentZoom < mMaxZoom) {
            return true;
        } else {
            return false;
        }
    }
});
gunner_dev
  • 357
  • 2
  • 11
Vijay
  • 1,082
  • 8
  • 6
1

To filter markers that have the same position, you could simply use a hashmasp, whose key is computed from the marker coordinates.

Something like:

Map<String, Marker> uniqueMarkers = new HashMap<String, Marker>();
for (Markers m : allMarkers) {
  // Compute a key to filter duplicates
  // You may need to account for small floating point precision errors by 
  // rounding those coordinates
  String key = m.getLatitude() + "|" + m.getLongitude();

  if (uniqueMarkers.get(key)!=null ) {
    // Skip if we have a marker with the same coordinates
    continue;
  }

  // Add marker and do something with it  
  uniqueMarkers.add(key, m);

  // ...
}
Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124