1

I have an android app with map populated with models having an attribute of sales.

I am able to implement a custom ClusterRenderer to display total sales instead of cluster size on the Cluster icon.

The problem that I have is eg.

Cluster A has 5 ClusterItems with total sales of 1M

Cluster B has 15 ClusterItems with total sales of 100k

Because of the default behavior of clustering, Cluster B is BIGGER than cluster A (because it has more ClusterItems)

Is there a way for me to highjack the Renderer so that the size of the Cluster marker scales with my TOTAL SALES instead of the Cluster size?

Any help will be very much appreciated!

Adding my clusterrenderer code

public class MyClusterRenderer extends DefaultClusterRenderer<Store> {

private final NavigableMap<Long, String> suffixes = new TreeMap<>();
private IconGenerator mClusterIconGenerator;
private Context context;

//for cluster icon
private ShapeDrawable mColoredCircleBackground;

public MyClusterRenderer(Context context, GoogleMap map, ClusterManager<Store> clusterManager) {
    super(context, map, clusterManager);
    this.context = context;

    //for label prefix processing
    suffixes.put(1_000L, "k");
    suffixes.put(1_000_000L, "M");
    suffixes.put(1_000_000_000L, "G");
    suffixes.put(1_000_000_000_000L, "T");
    suffixes.put(1_000_000_000_000_000L, "P");
    suffixes.put(1_000_000_000_000_000_000L, "E");

    mClusterIconGenerator = new IconGenerator(context);
    //pre processing for cluster icons
    mClusterIconGenerator.setContentView(makeSquareTextView(context));
    mClusterIconGenerator.setTextAppearance(R.style.amu_ClusterIcon_TextAppearance);
    mClusterIconGenerator.setBackground(makeClusterBackground());
}

private SquareTextView makeSquareTextView(Context context) {

    SquareTextView squareTextView = new SquareTextView(context);
    ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    squareTextView.setLayoutParams(layoutParams);
    squareTextView.setId(R.id.amu_text);
    int twelveDpi = 12 * getDensity();
    squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi);
    return squareTextView;
}

@Override
protected void onBeforeClusterItemRendered(Store item, MarkerOptions markerOptions) {
    //individual markers here
    markerOptions.icon(getIcon(item));
    super.onBeforeClusterItemRendered(item, markerOptions);
}

@Override
protected void onBeforeClusterRendered(Cluster<Store> cluster, MarkerOptions markerOptions) {
    Bitmap icon = mClusterIconGenerator.makeIcon(getTotalSalesWithFormat((List<Store>) cluster.getItems()));
    BitmapDescriptor descriptor = BitmapDescriptorFactory.fromBitmap(icon);
    markerOptions.icon(descriptor);
}

private int getDensity(){
    return (int) context.getResources().getDisplayMetrics().density;
}

private LayerDrawable makeClusterBackground() {
    mColoredCircleBackground = new ShapeDrawable(new OvalShape());
    mColoredCircleBackground.setColorFilter(context.getResources().getColor(R.color.My_green), PorterDuff.Mode.SRC_ATOP);
    ShapeDrawable outline = new ShapeDrawable(new OvalShape());
    outline.getPaint().setColor(context.getResources().getColor(android.R.color.transparent)); // Transparent white.
    LayerDrawable background = new LayerDrawable(new Drawable[]{outline, mColoredCircleBackground});
    int strokeWidth = getDensity() * 3;
    background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
    return background;
}

private String getTotalSalesWithFormat(List<Store> list){
    return format(getTotalSales(list));
}

private int getTotalSales(List<Store> list){
    int sum = 0;
    for(Store s : list){
        sum += s.getSales();
    }
    return sum;
}

private BitmapDescriptor getIcon(Store item){
    Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.circle);
    Bitmap mutable = bmp.copy(Bitmap.Config.ARGB_8888, true);
    Canvas canvas = new Canvas(mutable);

    Paint p = new Paint();
    p.setColor(Color.WHITE);

    canvas.drawText(String.valueOf(item.getSales()), 0, 50, p);

    return BitmapDescriptorFactory.fromBitmap(mutable);
}

private String format(long value) {
    //Long.MIN_VALUE == -Long.MIN_VALUE so we need an adjustment here
    if (value == Long.MIN_VALUE) return format(Long.MIN_VALUE + 1);
    if (value < 0) return "-" + format(-value);
    if (value < 1000) return Long.toString(value); //deal with easy case

    Map.Entry<Long, String> e = suffixes.floorEntry(value);
    Long divideBy = e.getKey();
    String suffix = e.getValue();

    long truncated = value / (divideBy / 10); //the number part of the output times 10
    boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10);
    return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix;
}

}

To better illustrate my issue, please find attached image. Notice that 6.3k is BIGGER than 23k (pardon my english) enter image description here

momoja
  • 938
  • 9
  • 23
  • what do you want exactly ..do you want to show total sales on the place of ClusterItems count ? for example you want to show 100k instead of 15 on cluster B – Digvijay Singh May 08 '17 at 13:18
  • Hi, I am able to do that already. My problem is that the cluster icons (circle) scale with the number of items inside it. I want the cluster icons to scale based on my sales. – momoja May 08 '17 at 13:22
  • can you paste your ClusterRenderer class code – Digvijay Singh May 08 '17 at 13:25
  • Hi @DigvijaySingh already put my code and an image to better illustrate my question. Most of my CustomRenderer is based off of the original code for `DefaultClusterRenderer` – momoja May 08 '17 at 13:30
  • hi @momoja i am getting the same issue i want to cluster my sales order in place of marker cluster.. can u put your code – Mohammad Adil Dec 12 '17 at 13:58

0 Answers0