Is there any method to change the background color of the cluster item? (the one that displays the count of the markers, like 100+, 200+ ...). I tried to look into the source code of the ClusterManager but could not find any option to change the color, but maybe someone here knows how to do that. I basically want to "materialify" those colors a bit.
Android maps utils cluster icon color
19.6k views Asked by qwertz AtThere are 6 answers
                        
                            
                        
                        
                            On
                            
                            
                                                    
                    
                Go to DefaultClusterRenderer (package com.google.maps.android.clustering.view;), and change the getColor() method to this:
private int getColor(int clusterSize) {
        // custom color
        double _logClusterSize; // log
        final int _maxRed = Integer.parseInt("ff", 16);
//        Log.v("kai", String.valueOf(_maxRed));
        final int _minRed = Integer.parseInt("e6", 16);
        final int _maxGreen = Integer.parseInt("a2", 16);
        final int _minGreen = Integer.parseInt("47", 16);
        final int _maxBlue = Integer.parseInt("93", 16);
        final int _minBlue = Integer.parseInt("2d", 16);
        final double _maxLogClusterSize = 10;
        double _step = (_maxRed - _minRed) / _maxLogClusterSize;
        _logClusterSize = Math.log(clusterSize);
        if(_logClusterSize > 10) _logClusterSize = 10;
        int _red = _maxRed - (int) (_step * _logClusterSize);
        int _green = _maxGreen - (int) (_step * _logClusterSize);
        int _blue = _maxBlue - (int) (_step * _logClusterSize);
        return Color.rgb(_red, _green, _blue);
//        final float hueRange = 220;
//        final float sizeRange = 300;
//        final float size = Math.min(clusterSize, sizeRange);
//        final float hue = (sizeRange - size) * (sizeRange - size) / (sizeRange * sizeRange) * hueRange;
//        return Color.HSVToColor(new float[]{
//                hue, 1f, .6f
//        });
    }
This will change the Cluster color to pink, in the range of the color defined by min(max) red(green, blue). Hope that help!
                        
                            
                        
                        
                            On
                            
                            
                                                    
                    
                I took some methods of superclass and partially remade them. Now i have beautiful standard clusters with my own colors.
public class CustomClusterRenderer extends DefaultClusterRenderer<GoogleMapMarker> {
private final IconGenerator mIconGenerator;
private ShapeDrawable mColoredCircleBackground;
private SparseArray<BitmapDescriptor> mIcons = new SparseArray();
private final float mDensity;
private Context mContext;
public CustomClusterRenderer(Context context, GoogleMap map,
                             ClusterManager<GoogleMapMarker> clusterManager) {
    super(context, map, clusterManager);
    this.mContext = context;
    this.mDensity = context.getResources().getDisplayMetrics().density;
    this.mIconGenerator = new IconGenerator(context);
    this.mIconGenerator.setContentView(this.makeSquareTextView(context));
    this.mIconGenerator.setTextAppearance(
            com.google.maps.android.R.style.ClusterIcon_TextAppearance);
    this.mIconGenerator.setBackground(this.makeClusterBackground());
}
@Override
protected void onBeforeClusterRendered(Cluster<GoogleMapMarker> cluster,
                                       MarkerOptions markerOptions) {
    // Main color
    int clusterColor = mContext.getResources().getColor(R.color.colorPrimary);
    int bucket = this.getBucket(cluster);
    BitmapDescriptor descriptor = this.mIcons.get(bucket);
    if(descriptor == null) {
        this.mColoredCircleBackground.getPaint().setColor(clusterColor);
        descriptor = BitmapDescriptorFactory.fromBitmap(
                this.mIconGenerator.makeIcon(this.getClusterText(bucket)));
        this.mIcons.put(bucket, descriptor);
    }
    markerOptions.icon(descriptor);
}
private SquareTextView makeSquareTextView(Context context) {
    SquareTextView squareTextView = new SquareTextView(context);
    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(-2, -2);
    squareTextView.setLayoutParams(layoutParams);
    squareTextView.setId(com.google.maps.android.R.id.text);
    int twelveDpi = (int)(12.0F * this.mDensity);
    squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi);
    return squareTextView;
}
private LayerDrawable makeClusterBackground() {
    // Outline color
    int clusterOutlineColor = mContext.getResources().getColor(R.color.colorWhite);
    this.mColoredCircleBackground = new ShapeDrawable(new OvalShape());
    ShapeDrawable outline = new ShapeDrawable(new OvalShape());
    outline.getPaint().setColor(clusterOutlineColor);
    LayerDrawable background = new LayerDrawable(
            new Drawable[]{outline, this.mColoredCircleBackground});
    int strokeWidth = (int)(this.mDensity * 3.0F);
    background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
    return background;
}
And then set renderer to Cluster Manager
mClusterManager = new ClusterManager<>(context, mGoogleMap);
mClusterManager.setRenderer(new CustomClusterRenderer(context, mGoogleMap, mClusterManager));
                        
                        
                            
                        
                        
                            On
                            
                            
                                                    
                    
                Sadly, overriding getColor doesn't work for me. But this looks enough to change the marker color (and something else):
class ClusterItemRenderer(
    context: Context, map: GoogleMap,
    clusterManager: ClusterManager<ClusterMarker>
) : DefaultClusterRenderer<ClusterMarker>(context, map, clusterManager) {
    override fun onBeforeClusterItemRendered(item: ClusterMarker, markerOptions: MarkerOptions) {
        val markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)
        markerOptions.icon(markerDescriptor)
    }
}
It's also possible to add updates according to the recommendations:
If you're using custom clustering (i.e, if you're extending
DefaultClusterRenderer), you must override two additional methods in v1:
onClusterItemUpdated()- should be the same* as youronBeforeClusterItemRendered()methodonClusterUpdated()- should be the same* as youronBeforeClusterRendered()method*Note that these methods can't be identical, as you need to use a
Markerinstead ofMarkerOptions
override fun onClusterItemUpdated(item: ClusterMarker, marker: Marker) {
    val markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)
    marker.setIcon(markerDescriptor)
}
                        
                        
                            
                        
                        
                            On
                            
                            
                                                    
                    
                Nice custom renderer with centered text and different sizes of clusters:
  public class MyClusterRenderer extends DefaultClusterRenderer<Station> {
    private final IconGenerator mClusterIconGeneratorBig = new IconGenerator(getCtx());
    private final IconGenerator mClusterIconGeneratorMed = new IconGenerator(getCtx());
    private final IconGenerator mClusterIconGeneratorSml = new IconGenerator(getCtx());
    final Drawable clusterIconBig = getResources().getDrawable(R.drawable.marker1);
    final Drawable clusterIconMed = getResources().getDrawable(R.drawable.marker2);
    final Drawable clusterIconSml = getResources().getDrawable(R.drawable.marker3);
    public MyClusterRenderer(Context context, GoogleMap map,
                             ClusterManager<Station> clusterManager) {
        super(context, map, clusterManager);
        setupIconGen(mClusterIconGeneratorBig, clusterIconBig, context);
        setupIconGen(mClusterIconGeneratorMed, clusterIconMed, context);
        setupIconGen(mClusterIconGeneratorSml, clusterIconSml, context);
    }
    private void setupIconGen(IconGenerator generator, Drawable drawable, Context context) {
        TextView textView = new TextView(context);
        textView.setTextAppearance(context, R.style.BubbleText);
        textView.setTypeface(App.FONTS[2]);
        textView.setId(com.google.maps.android.R.id.amu_text);
        textView.setGravity(android.view.Gravity.CENTER);
        textView.setLayoutParams(new FrameLayout.LayoutParams(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()));
        generator.setContentView(textView);
        generator.setBackground(drawable);
    }
    @Override
    protected void onBeforeClusterItemRendered(Station item, MarkerOptions markerOptions) {
        BitmapDescriptor markerDescriptor = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA);
        markerOptions.icon(markerDescriptor);
    }
    @Override
    protected void onClusterItemRendered(Station clusterItem, Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
    }
    @Override
    protected void onBeforeClusterRendered(Cluster<Station> cluster, MarkerOptions markerOptions) {
        if (cluster.getSize() > 20) {
            Bitmap icon = mClusterIconGeneratorBig.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        } else if (cluster.getSize() > 10) {
            Bitmap icon = mClusterIconGeneratorMed.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        } else {
            Bitmap icon = mClusterIconGeneratorSml.makeIcon(String.valueOf(cluster.getSize()));
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
        }
    }
    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        return cluster.getSize() > 5;
    }
}
                        
I was able to get a rough implementation working by using this demo from the library samples as a guide.
I used the
lensicon from the Material Design Icons from here. After downloading thelenszip I putic_lens_black_24dp.pngunder the drawable folder. Then I used the Drawable.setColorFilter() method to change the default color in the code.I was also able to change the default Marker color, and figured I would include that as well here.
First, set a Renderer by calling
setRenderer():Then, define the
MyClusterRendererclass:Full class code:
Result:
Initial app launch:
Zooming out, some clustering:
Zooming out again, all Markers clustered: