Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google map marker is replaced by bounding rectangle on zoom

I'm using SupportMapFragment inside Fragment and recent Android Map Utils for clustering. After Google Play Services update to 9.0.83 google single map markers are replaced by bounding rectangle on zoom. Only single markers are replaced, cluster markers are fine. Changing hardware acceleration parameter in app manifest doesn't change anything. How to fix it?

enter image description here

P.S.

compile 'com.google.android.gms:play-services-maps:8.4.0'
like image 898
Maksim Diakonov Avatar asked May 13 '16 13:05

Maksim Diakonov


1 Answers

I use simplified version of @bishop87's workaround from issue on github project. Also added caching for cluster bitmaps, which made it much more OOM-safer.

If you don't have Cluster renderer than use this one or move this code to your own:

SimpleClusterRenderer.java

public class SimpleClusterRenderer extends DefaultClusterRenderer<AuctionItem> {
    private static final int CLUSTER_PADDING = 12;
    private static final int ITEM_PADDING = 7;

    private final Bitmap mIconItemGreen;
    private final IconGenerator mIconClusterGenerator;
    private final float mDensity;

    public SimpleClusterRenderer(Context context, GoogleMap map, ClusterManager<AuctionItem> clusterManager) {
        super(context, map, clusterManager);

        mDensity = context.getResources().getDisplayMetrics().density;

        mIconClusterGenerator = new CachedIconGenerator(context);
        mIconClusterGenerator.setContentView(makeSquareTextView(context, CLUSTER_PADDING));
        mIconClusterGenerator.setTextAppearance(com.google.maps.android.R.style.ClusterIcon_TextAppearance);

        IconGenerator iconItemGenerator = new IconGenerator(context);
        iconItemGenerator.setContentView(makeSquareTextView(context, ITEM_PADDING));
        iconItemGenerator.setBackground(makeClusterBackground(ContextCompat.getColor(context, R.color.simple_green)));
        mIconItemGreen = iconItemGenerator.makeIcon();
    }

    @Override
    protected void onBeforeClusterItemRendered(AuctionItem item, MarkerOptions markerOptions) {
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(mIconItemGreen));
    }

    @Override
    protected void onBeforeClusterRendered(Cluster<AuctionItem> cluster, MarkerOptions markerOptions) {
        int clusterSize = getBucket(cluster);

        mIconClusterGenerator.setBackground(makeClusterBackground(getColor(clusterSize)));
        BitmapDescriptor descriptor = BitmapDescriptorFactory.fromBitmap(mIconClusterGenerator.makeIcon(getClusterText(clusterSize)));
        markerOptions.icon(descriptor);
    }

    @Override
    protected boolean shouldRenderAsCluster(Cluster<AuctionItem> cluster) {
        // Always render clusters.
        return cluster.getSize() > 1;
    }

    private int getColor(int clusterSize) {
        float size = Math.min((float) clusterSize, 300.0F);
        float hue = (300.0F - size) * (300.0F - size) / 90000.0F * 220.0F;
        return Color.HSVToColor(new float[]{hue, 1.0F, 0.6F});
    }

    private LayerDrawable makeClusterBackground(int color) {
        ShapeDrawable mColoredCircleBackground = new ShapeDrawable(new OvalShape());
        mColoredCircleBackground.getPaint().setColor(color);
        ShapeDrawable outline = new ShapeDrawable(new OvalShape());
        outline.getPaint().setColor(0x80ffffff);
        LayerDrawable background = new LayerDrawable(new Drawable[]{outline, mColoredCircleBackground});
        int strokeWidth = (int) (mDensity * 3.0F);
        background.setLayerInset(1, strokeWidth, strokeWidth, strokeWidth, strokeWidth);
        return background;
    }

    private SquareTextView makeSquareTextView(Context context, int padding) {
        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.text);
        int paddingDpi = (int) (padding * mDensity);
        squareTextView.setPadding(paddingDpi, paddingDpi, paddingDpi, paddingDpi);
        return squareTextView;
    }
}

CachedIconGenerator.java

public class CachedIconGenerator extends IconGenerator {

    private final LruCache<String, Bitmap> mBitmapsCache;
    private String mText;

    public CachedIconGenerator(Context context) {
        super(context);

        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

        // Use 1/8th of the available memory for this memory cache.
        final int cacheSize = maxMemory / 8;
        mBitmapsCache = new LruCache<String, Bitmap>(cacheSize) {
            @Override
            protected int sizeOf(String key, Bitmap bitmap) {
                // The cache size will be measured in kilobytes rather than
                // number of items.
                return bitmap.getByteCount() / 1024;
            }
        };
    }

    public Bitmap makeIcon(String text) {
        mText = text;
        return super.makeIcon(text);
    }

    @Override
    public Bitmap makeIcon() {
        if (TextUtils.isEmpty(mText)) {
            return super.makeIcon();
        } else {
            Bitmap bitmap = mBitmapsCache.get(mText);
            if (bitmap == null) {
                bitmap = super.makeIcon();
                mBitmapsCache.put(mText, bitmap);
            }
            return bitmap;
        }
    }
}

P.S. You also need to replace R.color.simple_green with pin colour you want.

P.P.S. Forgot to mention, that this approach has negligible performance impact. So it would be better to update this solution with different approaches for Play Services 9.0.83 and others, if Google will fix this issue on next Play Services app release.

like image 117
Oleksandr Avatar answered Oct 05 '22 05:10

Oleksandr