Подтвердить что ты не робот

ClusterManager отображает маркеры Google maps v2 utils

Привет, я делаю запрос сервера, и когда я получил запрос от сервера, я выполняю на Ui Thread clusterManager.addItem(), но эти элементы не отображаются на карте, только когда я делаю обновление масштабирования (+, -). Кроме того, я попытался отладить средство визуализации, но onBeforeClusterRendered/onBeforeClusterItemRendered не вызывается, пока я не обновляю масштаб карты. Любые идеи по обновлению map/clusterManager/markers?

        MarkerManager markerManager = new MarkerManager(map);
        clusterManager = new ClusterManager<TweetClusterItem>(getActivity(), map, markerManager);
        clusterManager.setRenderer(new TweetClusterRenderer(getActivity(), map, clusterManager, defaultMarker));
        clusterManager.setOnClusterClickListener(this);
        clusterManager.setOnClusterInfoWindowClickListener(this);
        clusterManager.setOnClusterItemClickListener(this);
        clusterManager.setOnClusterItemInfoWindowClickListener(this);

        UiSettings uiSettings = map.getUiSettings();
        uiSettings.setZoomControlsEnabled(true);
        uiSettings.setMyLocationButtonEnabled(false);

        map.setOnCameraChangeListener(clusterManager);
        map.setOnMarkerClickListener(clusterManager);
        map.setOnInfoWindowClickListener(clusterManager);
        map.setOnMapClickListener(this);
4b9b3361

Ответ 1

Кажется, я нашел обходное решение.

ClusterManager использует средство визуализации, в этом случае он наследует от DefaultClusterRenderer, который использует внутренний кеш, кеш маркеров, которые добавляются к карте. Вы можете получить доступ к добавленным маркерам на карте, я не использую информационное окно, поэтому я добавляю маркер options.title() идентификатор для последующего поиска этого маркера, поэтому:

@Override
protected void onBeforeClusterItemRendered(TweetClusterItem item, MarkerOptions markerOptions) {

     .... Blabla code....          
            markerOptions.title(Long.toString(tweet.getId()));
     .... Blabla code....


}

и когда я хочу перезагрузить объект clusterItem, я вызываю этот метод:

/**
  * Workarround to repaint markers
  * @param item item to repaint
 */
  public void reloadMarker(TweetClusterItem item) {

        MarkerManager.Collection markerCollection = clusterManager.getMarkerCollection();
        Collection<Marker> markers = markerCollection.getMarkers();
        String strId = Long.toString(item.getTweet().getId());
        for (Marker m : markers) {
            if (strId.equals(m.getTitle())) {
                m.setIcon( ICON TO SET);
                break;
            }
        }

    }

Может быть, немного взломан, но он работает, и я не нашел другого способа сделать это. Если вы нашли другой лучший способ, поделитесь:)

Ответ 2

mClusterManager.cluster();

принудительно повторно кластеризуйте элементы при добавлении нового элемента.

Ответ 3

У меня была та же проблема. Это также усугублялось тем, что я делаю индивидуальный рендеринг в onBeforeClusterItemRendered в моем подклассе DefaultClusterRenderer.

Мое решение состояло в том, чтобы создать новый экземпляр моего подкласса DefaultClusterRenderer и снова вызвать setRenderer в ClusterManager. Это сбрасывает все кэшированные значки и воссоздает все.

Это взломанная, грубая сила и раздражающе неэффективная, но она действительно работает. Это был единственный подход, который я нашел, который работал, поскольку библиотека, похоже, не имеет явной поддержки для этого.

Ответ 4

Вы можете получить определенные маркеры, соответствующие их кластерным или кластерным элементам, и наоборот в O (1), используя DefaultClusterRenderer getMarker(), getCluster() и getClusterItem() (установите собственный рендеринг для доступа к объекту рендеринга).

Используйте эти методы для изменения маркеров ваших элементов, когда вам нужно.

   ...
   DefaultClusterRenderer mRenderer = ...
   mClusterManager.setRenderer(mRenderer);
   ...

public void reloadMarker(ClusterItem item) {
    mRenderer.getMarker(item).setIcon(YOUR_ICON);
}

Я бы не рекомендовал сохранять их в другом месте, поскольку эти методы возвращают объекты кэша визуализатора.

Ответ 5

mClusterManager.cluster(); не работал у меня

это произошло, хотя:

if (mMap != null) {
    CameraPosition currentCameraPosition = mMap.getCameraPosition();
    mMap.moveCamera(CameraUpdateFactory.newCameraPosition(currentCameraPosition));
}

Это вызвало вызов onCameraChange, где я уже выполнял mClusterManager.clearItems()... mClusterManager.addItem(..) - для объектов внутри видимой области... mClusterManager.cluster()

Контекст для меня заключался в том, что контакты исчезали при возврате назад к фрагменту, отображающему карту (- только на определенных устройствах, например Nexus 7, где не было автоматического вызова OnCameraChange)

Ответ 6

У меня была такая же точная проблема. Ни один из предложенных решений не работал у меня. Я создал класс, который расширяет DefaultClusterRenderer и добавляет общедоступный метод updateClusterItem (ClusterItem clusterItem), который заставит маркер, связанный с этим ClusterItem, перерисовываться (работает как с кластерами, так и с элементами кластера).

import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.maps.android.clustering.Cluster;
import com.google.maps.android.clustering.ClusterItem;
import com.google.maps.android.clustering.ClusterManager;
import com.google.maps.android.clustering.view.DefaultClusterRenderer;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;


public abstract class CustomClusterRenderer<T extends ClusterItem>
        extends DefaultClusterRenderer<T> {

    private ClusterManager<T> mClusterManager;
    private Map<T, Marker> mClusterMap = new HashMap<>();

    public CustomClusterRenderer(Context context, GoogleMap map,
                                 ClusterManager<T> clusterManager) {
        super(context, map, clusterManager);
        mClusterManager = clusterManager;
    }


    @Override
    @CallSuper
    protected void onClusterItemRendered(T clusterItem, Marker marker) {
        super.onClusterItemRendered(clusterItem, marker);
        mClusterMap.remove(clusterItem);
        cleanCache();
    }

    @Override
    @CallSuper
    protected void onClusterRendered(Cluster<T> cluster, Marker marker) {
        super.onClusterRendered(cluster, marker);
        for (T clusterItem : cluster.getItems()) {
            mClusterMap.put(clusterItem, marker);
        }
        cleanCache();
    }

    public void updateClusterItem(T clusterItem) {
        Marker marker = getMarker(clusterItem);
        boolean isCluster = false;
        if (marker == null) {
            marker = mClusterMap.get(clusterItem);
            isCluster = marker != null;
        }
        if (marker != null) {
            MarkerOptions options = getMarkerOptionsFromMarker(marker);
            if (isCluster) {
                Cluster cluster = getCluster(marker);
                onBeforeClusterRendered(cluster, options);
            } else {
                onBeforeClusterItemRendered(clusterItem, options);
            }
            loadMarkerWithMarkerOptions(marker, options);
        }
    }

    private void cleanCache() {
        ArrayList<T> deleteQueue = new ArrayList<>();
        Collection<Marker> clusterMarkers = mClusterManager
                .getClusterMarkerCollection().getMarkers();

        for (T clusterItem : mClusterMap.keySet()) {
            if (!clusterMarkers.contains(mClusterMap.get(clusterItem))) {
                deleteQueue.add(clusterItem);
            }
        }

        for (T clusterItem : deleteQueue) {
            mClusterMap.remove(clusterItem);
        }
        deleteQueue.clear();
    }

    private MarkerOptions getMarkerOptionsFromMarker(@NonNull Marker marker) {
        MarkerOptions options = new MarkerOptions();

        options.alpha(marker.getAlpha());
        options.draggable(marker.isDraggable());
        options.flat(marker.isFlat());
        options.position(marker.getPosition());
        options.rotation(marker.getRotation());
        options.title(marker.getTitle());
        options.snippet(marker.getSnippet());
        options.visible(marker.isVisible());
        options.zIndex(marker.getZIndex());

        return options;
    }

    private void loadMarkerWithMarkerOptions(@NonNull Marker marker,
                                             @NonNull MarkerOptions options) {
        marker.setAlpha(options.getAlpha());
        marker.setDraggable(options.isDraggable());
        marker.setFlat(options.isFlat());
        marker.setPosition(options.getPosition());
        marker.setRotation(options.getRotation());
        marker.setTitle(options.getTitle());
        marker.setSnippet(options.getSnippet());
        marker.setVisible(options.isVisible());
        marker.setZIndex(options.getZIndex());
        marker.setIcon(options.getIcon());
        marker.setAnchor(options.getAnchorU(), options.getAnchorV());
        marker.setInfoWindowAnchor(options.getInfoWindowAnchorU(), options.getInfoWindowAnchorV());
    }

}

Ответ 7

Мое решение с помощью CustomRenderer, расширяющего DefaultClusterRenderer

 protected void onClusterItemRendered(T clusterItem, Marker marker) {
    marker.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}