DefaultClusterRenderer getMarker () returns null when scaling

I want to change the background of the cluster marker when clicked. I do it through

@Override onClusterClick(Cluster<MyObject> cluster) { Marker marker = renderer.getMarker(cluster); marker.setIcon(....); } 

This works great for one case: when I zoom in or out and the number of cluster markers does not change. For example, if I had a cluster of 15 clusters and 5, and then increase the level to or from, the same two clusters remain. Clicking on one of them now renderer.getMarker(cluster) returns null. If they are re-clustered after scaling, getMarker is not zero.

My DefaultClusterRenderer is below. I checked the marker on onClusteredRendered and it was never null. Is this a bug in the DefaultClusterRenderer or do I need to do something else?

 private class MyRenderer extends DefaultClusterRenderer<MyObject> { private IconGenerator iconGenerator; private float density; public MyRenderer(Context context, GoogleMap map, ClusterManager<MyObject> clusterManager) { super(context, map, clusterManager); density = context.getResources().getDisplayMetrics().density; } @Override protected void onBeforeClusterItemRendered(MyObject item, MarkerOptions markerOptions) { markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.my_pin)); } @Override protected void onBeforeClusterRendered(Cluster<MyObject> cluster, MarkerOptions markerOptions) { if(iconGenerator == null) { iconGenerator = new IconGenerator(getActivity()); iconGenerator.setContentView(makeTextView(getActivity())); } iconGenerator.setBackground(makeBackground(false)); markerOptions.icon(BitmapDescriptorFactory.fromBitmap(iconGenerator.makeIcon(String.valueOf(cluster.getSize())))); } @Override protected void onClusterRendered(Cluster<MyObject> cluster, Marker marker) { super.onClusterRendered(cluster, marker); // Marker is never null here } @Override protected boolean shouldRenderAsCluster(Cluster<MyObject> cluster) { return cluster.getSize() > 1; } private ShapeDrawable makeBackground(boolean isClicked) { ShapeDrawable background = new ShapeDrawable(new OvalShape()); background.setColorFilter(ContextCompat.getColor(getActivity(), isClicked ? R.color.cluster_marker_clicked : R.color.cluster_marker_unclicked), PorterDuff.Mode.SRC_ATOP); return background; } private SquareTextView makeTextView(Context context) { SquareTextView squareTextView = new SquareTextView(context); ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(-2, -2); squareTextView.setLayoutParams(layoutParams); squareTextView.setTextColor(ContextCompat.getColor(getActivity(), R.color.white)); squareTextView.setTypeface(Utils.getFontBold(getActivity())); squareTextView.setId(com.google.maps.android.R.id.text); int twelveDpi = (int) (12.0F * density); squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi); return squareTextView; } public IconGenerator getIconGenerator(boolean isClicked) { iconGenerator.setBackground(makeBackground(isClicked)); return iconGenerator; } } 

Initializing ClusterManager:

  final ClusterManager<MyObject> mClusterManager = new ClusterManager<>(getActivity(), googleMap); mClusterManager.addItems(items); renderer = new CustomRenderer(getActivity(), googleMap, mClusterManager); mClusterManager.setRenderer(renderer); mClusterManager.cluster(); mClusterManager.setOnClusterItemClickListener(this); googleMap.setOnMarkerClickListener(mClusterManager); 

@antonio: This initialization works for me:

 public class MapsActivity extends FragmentActivity implements ClusterManager.OnClusterClickListener<MyObject> { // ... private void setUpClusterer() { googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); mClusterManager = new ClusterManager<MyObject>(this, googleMap); mClusterManager.setOnClusterClickListener(this); renderer = new MyRenderer(this, googleMap, mClusterManager); mClusterManager.setRenderer(renderer); googleMap.setOnCameraChangeListener(mClusterManager); googleMap.setOnMarkerClickListener(mClusterManager); addItems(); } private void addItems() { // Set some lat/lng coordinates to start with. double lat = 51.5145160; double lng = -0.1270060; // Add ten cluster items in close proximity, for purposes of this example. for (int i = 0; i < 10; i++) { double offset = i / 60d; lat = lat + offset; lng = lng + offset; MyObject offsetItem = new MyObject(lat, lng); mClusterManager.addItem(offsetItem); } } @Override public boolean onClusterClick(final Cluster<MyObject> cluster) { Marker marker = renderer.getMarker(cluster); marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.my_newpin)); return true; } } 
+8
android google-maps markerclusterer
source share
1 answer

Failed to get renderer.getMarker(cluster) to return the marker in this case above. Work around was the creation of:

 Map <Cluster<MyObject>, Marker> clusterMarkerMap = new HashMap<>(); 

then add them to the DefaultClusterRenderer callback because the token never matters:

 @Override protected void onClusterRendered(Cluster<MyObject> cluster, Marker marker) { super.onClusterRendered(cluster, marker); clusterMarkerMap.put(cluster, marker); } 

Since the DefaultClusterManager clears them when the camera position changes, wipe the cluster marker card before creating new ones:

  googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { @Override public void onCameraChange(CameraPosition cameraPosition) { // Clear the map here because the markers will be recreated // when the manager is notified of a (zoom level) camera change if(zoomLevelChanged) clusterMarkerMap.clear(); mClusterManager.onCameraChange(cameraPosition); } }); 

Now I can successfully get the clusterMarkerMap.get(cluster) token

+3
source share

All Articles