When you put your model objects/items into the cluster manager, it will create the markers and group them to clusters if necessary. This is awesome!!
But what if the items change and upon this change you want to have different marker?
Update the api with an
updateItem(Item)
method. Its the same instance of the added item but has updated attributes.
What I first tried was just replacing the item list
getMap().clear();
mClusterManager.clearItems()
mClusterManager.addItems(items);
mClusterManager.cluster();
This worked only for visible clusters when map was zoomed out. However when map was zoomed in, visible map markers were removed by the above code. You have to zoom out until cluster appears and zoom in again to see the markers.
Currently I am doing this, completely reinitiate the clusterManager when I need to update models and markers. I am not dealing with so much markers (max 200).
@broady Is this ok regarding performance/memory? Nevertheless the cluster api could need some rewrite :+1:
This commit makes it possible: https://github.com/googlemaps/android-maps-utils/commit/49d42d65c1eb5f92ce4239ab82ad7915ba1d9e69#
@Shusshu How? I am having the same problem with clearing items and adding them back. Please see this issue: https://github.com/googlemaps/android-maps-utils/issues/168
i would love to know if there's a solution to updating a model and having the info window refreshed.
I guess we still need to kill all markers and then re-add them back as new ones, sadness eternal ...
I can confirm that Idea 2 works correctly. In fact I can confirm that removeItem()+addItem()+cluster() works correctly if you have a correct Renderer.
You must ensure you use a custom renderer that overrides onClusterItemRendered() and onClusterRendered()
Default renderer only uses onBeforeClusterRendered() that is only called once to create the initial marker.
@lujop How did you go about overriding onClusterItemRendered() and onClusterRendered()? I'm trying to re-draw a marker after it's position changes. The new position will show if I zoom in/out but not if I'm zoomed in to the marker level. cluster() works on clusters, but not individual markers.
As I said - if you want to update a single marker, remove the item (not the marker), add the item again, and run cluster() - the function gets the updated set of items from its array and then refreshes all of its markers on the map.
In nativescript:
// remove previous item
dis.cluster_manager.removeItem(cluster_item);
// if following data goes into constructor directly, they somehow become null, so save them seperately outside here
var temp_data = data_units.existing[i];
var updated_position = new dis.maps.model.LatLng(temp_data.latitude, temp_data.longitude);
// adding item
var item = new dis.clustering.ClusterItem({
getTitle: function() {},
getSnippet: function() {},
getPosition: function () {
return updated_position;
},
userData: temp_data
});
dis.cluster_manager.addItem(item);
// commit changes
dis.cluster_manager.cluster();
By me object it it still not working correctly
I Use
fun setUpMarkers(poiList:List<ClusterItem>){
mGoogleMap?.clear()
mClusterManager?.clearItems()
poiList.forEachIndexed { index, poi -> run{
mClusterManager?.addItem(poi)
if (index < 6)
boundBuilder.include(poi.latLng)
}}
[...]
mGoogleMap?.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, mapPadding), cameraUpdateListener)
}
camerUpdateListener
private val cameraUpdateListener = object : GoogleMap.CancelableCallback {
override fun onFinish() {
mClusterManager?.cluster()
}
override fun onCancel() {
mClusterManager?.cluster()
}
}
In run time I delivere different list of CluterItems to my function, after animated zoom, sometimes some of markers are not visible - until i zoom out/in (force cluter algorithm to run). A assume that clearItems if also woring inpredictable - sometimes remove more soetimes less items
I also cannot refresh marker icons, the "java.lang.IllegalArgumentException: Unmanaged descriptor" always appears when I try to get a marker from Renderer and setIcon for it. Thanks!
Hello all,
I was facing similar issue when downloading images via Glide.
Now it is working fine for me.
What I did was call mClusterManager.cluster(); after all images were downloaded in onPostExecute.
@Override
protected Void doInBackground(Void... voids) {
if (fetchUserMapData != null) {
for (int i = 0; i < fetchUserMapData.getDiscoveredUsers().size(); i++) {
LatLng latLng = new LatLng(fetchUserMapData.getDiscoveredUsers().get(i).getUserLatitude().doubleValue(),
fetchUserMapData.getDiscoveredUsers().get(i).getUserLongitude().doubleValue());
Bitmap bitmap;
try {
bitmap = Glide.with(MapFragment.this)
.load(fetchUserMapData.getDiscoveredUsers().get(i).getProfilePictureUrl())
.asBitmap()
.into(200, 200).get();
} catch (Exception e) {
e.printStackTrace();
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.user_image_placeholder);
}
mClusterManager.addItem(new Person(latLng,
fetchUserMapData.getDiscoveredUsers().get(i).getUsername(),
bitmap));
}
}
return null;
}
I have tested a couple of times. But, I would prefer good amount of testing before being sure.
Like @Shusshu said , getMarker() can solve the issue
In my case it looks like this:
In Activity:
@Override
public void onMapReady(GoogleMap googleMap) {
super.onMapReady(googleMap);
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
mClusterManager = new ClusterManager<>(activity, getGoogleMap());
mClusterManager.setAlgorithm(new NonHierarchicalDistanceBasedAlgorithm<>());
mClusterManager.setRenderer(new PlaceRenderer(activity, getGoogleMap(), mClusterManager));
mClusterManager.setOnClusterClickListener(this);
mClusterManager.setOnClusterItemClickListener(this);
getGoogleMap().setOnCameraIdleListener(mClusterManager);
getGoogleMap().setOnMarkerClickListener(mClusterManager);
getGoogleMap().setOnInfoWindowClickListener(mClusterManager);
getGoogleMap().setOnMapClickListener(latLng -> {
setItemChecked(null);
});
}
@Override
public boolean onClusterItemClick(PlaceCluster placesCluster) {
mGoogleMap.animateCamera(CameraUpdateFactory
.newLatLngZoom(placesCluster.getPosition(), getGoogleMap().getCameraPosition().zoom));
setItemChecked(placesCluster);
return true;
}
private void setItemChecked(@Nullable PlaceCluster placesCluster) {
PlaceRenderer renderer = (PlaceRenderer) mClusterManager.getRenderer();
for (PlaceCluster item: mClusterManager.getAlgorithm().getItems()) {
item.setChecked(false);
if (placesCluster!=null && item.equals(placesCluster)){
placesCluster.setChecked(true);
}
renderer.setUpdateMarker(item);
}
}
PlaceRenderer :
public class PlaceRenderer extends DefaultClusterRenderer<PlaceCluster> {
...
public void setUpdateMarker(PlaceCluster place) {
Marker marker = getMarker(place);
if (marker != null) {
marker.setIcon(place.isChecked() ? mPlaceMarkerDescriptorChecked : mPlaceMarkerDescriptorDefault);
}
}
...
PlaceCluster :
public class PlaceCluster implements ClusterItem, Checkable {
...
}
Thank you @Kolyall !!
Making a "setUpdateMarker" method worked perfectly in my Renderer!
@Kolyall getMarker() always returns null for me. No way to get that code of yours working..
idea 2 also worked nice for me
`
val persons: HashMap
fun refreshCluster() {
clusterManager?.clearItems()
clusterManager?.addItems(persons.values)
clusterManager?.cluster()
}`
where Person is a
data class Person(val userDoc: QueryDocumentSnapshot) : ClusterItem { ...
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!
Most helpful comment
Like @Shusshu said ,
getMarker()can solve the issueIn my case it looks like this:
In Activity:
PlaceRenderer :
PlaceCluster :