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)