Пользовательские маркеры Android MapView имеют одинаковый размер


Я пишу приложение, которое покажет карту с кучей маркеров на ней. Я хочу, чтобы маркеры были динамическими (отображая динамическое содержимое на них). Поскольку содержание маркеров является динамическим, размер каждого маркера отличается.

Я нашел это в документации, где говорится ,что " разные маркеры могут быть возвращены для разных состояний. Различные маркеры могут иметь различные границы." здесь: https://developers.google.com/maps/documentation/android/reference/com/google/android/maps/OverlayItem#getMarker(int) Я предполагаю, что это означает, что несколько маркеров на одном и том же наложении могут быть разных размеров. Это правильно?

У меня есть ArrayList на моем оверлее (расширяет BalloonItemizedOverlay). Метод createitem () наложения выглядит следующим образом:

@Override
protected OverlayItem createItem(final int index)
{
    final Person person = people.get(index);
    final GeoPoint gp = new GeoPoint(person.getLat(), person.getLng());

    final OverlayItem oi = new OverlayItem(gp, person.getName(), person.getName());
    oi.setMarker(new PersonDrawable(defaultMarker, person));

    return oi;
}

Тогда в моем PersonDrawable есть drawable, который имеет патч 9 в качестве фонового изображения, а затем рисует текст на сверху:

public PersonDrawable(final Drawable iBackground, final Person person)
{
    background = iBackground;
    text = person.getName();
    padding = new Rect();

    if (background instanceof NinePatchDrawable)
    {
        // This is getting hit, and just sets the value of the padding
        final NinePatchDrawable ninePatch = (NinePatchDrawable) background;
        ninePatch.getPadding(padding);
    }

    // set the bounds of the marker
    bounds = background.getBounds();

    paint = new Paint();
    paint.setColor(Color.rgb(255, 255, 255));
    paint.setFakeBoldText(true);
    paint.setTextSize(30);

    // find the bounds of the text
    final Rect textBounds = new Rect();
    paint.getTextBounds(text, 0, text.length(), textBounds);

    // set the left and right bounds to that of the text plus the padding (then center it)
    bounds.left = 0 - (textBounds.width() / 2) - padding.left;
    bounds.right = 0 + (textBounds.width() / 2) + padding.right;

    // set the bounds of the drawable
    setBounds(bounds);
}

@Override
public void draw(final Canvas canvas)
{
    // when it's time to draw, draw the background
    background.draw(canvas);
    // then draw the text within the padding
    canvas.drawText(text, bounds.left + padding.left, bounds.bottom - padding.bottom, paint);
}
Каждый маркер имеет определенный набор границ, даже после того, как он нарисован на наложении, его границы различны. MapView (или Overlay) не использует повторно объекты из createItem(). Однако Overlay, похоже, всегда выбирает один маркер и предполагает, что это размер для всех маркеров. Это просто такое поведение? Есть ли что-то, что я могу сделать, чтобы заставить его уважать границы по-разному для каждого маркера?

Вот некоторые фотографии, когда он решает выбрать более крупный маркер вещи получаются ОК:

Росомаха длиннее, так что все выглядит нормально.

Однако, когда он выбирает использовать меньший маркер в качестве размера:

Зверь немного короче и переливается

1 2

1 ответ:

Проблема заключается в том, что когда Drawable загружается из ресурсов, он рассматривается как совместно используемые ресурсы. Из документации Drawable:

По умолчанию все экземпляры drawables, загруженные из одного и того же ресурса, имеют общее состояние; если вы измените состояние одного экземпляра, все остальные экземпляры получат такое же изменение.

В OverlayItem предполагается, что Drawable будет одинакового размера во всем. Эффект, который вы видите, заключается в том, что последнее модификация Drawable переопределяет все предыдущие модификации, поэтому все отображения Drawable отображаются точно так же.

Решение состоит в том, чтобы предотвратить совместное использование модификаций Drawable. Это можно сделать с помощью метода mutate() в сочетании с несколькими загрузками извлекаемого из ресурса. Это следует делать совместно с описанным выше конструктором PersonDrawable.