【问题标题】:Google map marker is replaced by bounding rectangle on zoom谷歌地图标记被缩放时的边界矩形取代
【发布时间】:2016-05-13 13:26:27
【问题描述】:

我在 Fragment 中使用 SupportMapFragment 和最近的 Android Map Utils 进行聚类。在 Google Play 服务更新到 9.0.83 之后,google 单个地图标记被缩放时的边界矩形所取代。只有单个标记被替换,集群标记很好。更改应用清单中的硬件加速参数不会改变任何内容。如何解决?

附言

compile 'com.google.android.gms:play-services-maps:8.4.0'

【问题讨论】:

标签: android google-maps google-play-services


【解决方案1】:

我使用@bishop87 的解决方法from issue on github project 的简化版本。还为集群位图添加了缓存,使其更加 OOM 安全。

如果您没有集群渲染器,请使用此渲染器或将此代码移至您自己的:

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;
        }
    }
}

附:您还需要将R.color.simple_green 替换为您想要的引脚颜色。

附言忘了提一下,这种方法对性能的影响可以忽略不计。因此,如果 Google 会在下一个 Play Services 应用程序版本中解决此问题,最好使用 Play Services 9.0.83 和其他版本的不同方法更新此解决方案。

【讨论】:

  • 为每个项目创建自己的 BitmapDescriptor 可能会在某些设备上导致 OutOfMemoryException 或类似情况。据我了解,这是因为集群库在重新计算集群版本之前会显示所有点。
  • @tse,不幸的是,你是对的。但是我已经用缓存更新了我的项目,现在它更安全了。我今天也会更新这个答案。
  • 是的,解决方案有效 - 但会产生很多 OutOfMemoryException(s)。
  • @Alexandr 你答应告诉我们更好的解决方法,而不会出现内存不足的异常
  • @tse,谢谢你的提醒。请参阅添加的 CachedIconGenerator。所有优化都在那里。
【解决方案2】:

根据 tyczj,当 Google Play 服务(专有二进制文件)更新到 9.0.x 时,这种情况就开始发生了。

从 Github 问题讨论的外观来看,解决方法是:

gmaps-api-issues 页面中可能的解决方法:

改变 marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.drawableid));

到 marker.setIcon(BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.drawableid))); //可能会影响一般内存消耗 tho(?),我没有测试超过应用程序中报告的 问题。

还要注意:

我可以确认这个问题。除了@Mavamaarten,您不得 重复使用标记图像。

(来源:https://github.com/googlemaps/android-maps-utils/issues/276

【讨论】:

  • 最后一部分是什么意思。 “你不能重复使用标记图像”??
  • 基本上,解决方法是您总是加载新的位图实例...而不是共享同一个。
  • 我正在共享同一个,但我没有得到错误。这正常吗?
  • @RayW 但您可以重用位图,只需将位图描述符更改为 LRUCache 中的位图
【解决方案3】:

对我来说,问题发生在以下情况:(1) 我删除带有自定义图标的标记或 (2) 在创建后设置新图标...

解决第一种情况,需要在remove之前设置默认图标...

if (marker != null) {
    marker.setIcon(BitmapDescriptorFactory.defaultMarker());
    marker.remove();
}

要解决第二种情况,您需要使用新的自定义图标添加标记的副本,然后在相同的第一种情况下删除...

在谷歌地图团队解决这个问题之前,它是一个解决方案......

祝你好运……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多