Reputation: 81
I am trying to use two ClusterManager for Google Map , But I am able to add only one clustermanager and it's item click event,
googleMap.setOnMarkerClickListener(mClusterManager);
and
mClusterManager.setOnClusterItemClickListener(new OnClusterItemClickListener<Person>() {
@Override
public boolean onClusterItemClick(Person item) {
Log.v("Cluster Click", "Item Click:"+item.getName());
return true;
}
});
How can I add one more clustermanager to googlemap?
Thanks in advance.
Upvotes: 8
Views: 3864
Reputation: 1
I know this might be late, but it might help someone who encounters this poorly documented issue in the future.
To successfully add multiple clusters to Google Maps that work independently, the most important and often overlooked step is to add:
MarkerManager markerManager = new MarkerManager(gMap);
You then use this MarkerManager to create your clusters:
ClusterManager<MyItemA> clusterManagerA = new ClusterManager<>(this, gMap, markerManager);
ClusterManager<MyItemB> clusterManagerB = new ClusterManager<>(this, gMap, markerManager);
Notice that both clusters are created using the same MarkerManager, and this is essential. If you create two different MarkerManager instances, only the last ClusterManager you defined (in this case, clusterManagerB) will handle the clicks and other interactions, effectively ignoring the first one.
I'm not 100% sure why this happens, but my educated guess, which I’m about 90% confident in, is that when you create a ClusterManager tied to the map without passing a MarkerManager like this:
ClusterManager<MyItemA> clusterManagerA = new ClusterManager<>(this, gMap);
it defaults to creating a new MarkerManager, as can be seen in the constructor:
public ClusterManager(Context context, GoogleMap map) {
this(context, map, new MarkerManager(map));
}
This means the previous MarkerManager associated with the map is effectively replaced (as indicated by new MarkerManager(map)), capturing all click events.
However, if you use the constructor where you pass an existing MarkerManager, then it simply adds the clicks from the new cluster to the same MarkerManager. Here’s the constructor code for reference:
public ClusterManager(Context context, GoogleMap map, MarkerManager markerManager) {
mMap = map;
mMarkerManager = markerManager;
mClusterMarkers = markerManager.newCollection();
mMarkers = markerManager.newCollection();
mRenderer = new DefaultClusterRenderer<>(context, map, this);
mAlgorithm = new ScreenBasedAlgorithmAdapter<>(new PreCachingAlgorithmDecorator<>(
new NonHierarchicalDistanceBasedAlgorithm<T>()));
mClusterTask = new ClusterTask();
mRenderer.onAdd();
}
So, the key takeaway is to create a shared MarkerManager before creating multiple clusters and pass that same MarkerManager to each ClusterManager.
And don't forget to add:
mMap.setOnCameraIdleListener(() -> {
clusterManagerA.onCameraIdle();
clusterManagerB.onCameraIdle();
});
so that your clusters expand and contract after zooming the map.
Upvotes: 0
Reputation: 978
Here is how I did it: KOTLIN version
override fun onMapReady(googleMap: GoogleMap?) {
this.googleMap = googleMap
//Step 1
val markerManager = MarkerManager(googleMap) // your googleMap instance
//Step 2
mEquipmentClusterManager = ClusterManager(activity, googleMap, markerManager)
mCustomerClusterManager = ClusterManager(activity, googleMap, markerManager)
googleMap.setOnMarkerClickListener(markerManager)
googleMap.setOnCameraIdleListener(this)
//Step 3
val rendererCustomer =CustomerAroundMeMapPinsCluster(activity,googleMap, mCustomerClusterManager)
val rendererEquipmentRental = EquipmentAroundMeMapPinsCluster(activity,googleMap,mEquipmentClusterManager)
//Step 4
mCustomerClusterManager.setOnClusterClickListener {
Toast.makeText(context, "Customer Cluster click", Toast.LENGTH_SHORT).show()
onClusterClick(it)
return@setOnClusterClickListener false
}
mCustomerClusterManager.setOnClusterItemClickListener {
Toast.makeText(context, "Customer item click", Toast.LENGTH_SHORT).show()
return@setOnClusterItemClickListener false
}
mEquipmentClusterManager.setOnClusterClickListener {
Toast.makeText(context, "Equipment Cluster click", Toast.LENGTH_SHORT).show()
return@setOnClusterClickListener true
}
mEquipmentClusterManager.setOnClusterItemClickListener {
// there is a ticket for this
Toast.makeText(context, "Equipment item clicked", Toast.LENGTH_SHORT).show()
return@setOnClusterItemClickListener false
}
mCustomerClusterManager.renderer = rendererCustomer
mEquipmentClusterManager.renderer = rendererEquipmentRental
}
override fun onCameraIdle() {
mEquipmentClusterManager.cluster()
mCustomerClusterManager.cluster()
}
Upvotes: 0
Reputation: 435
you can use MarkerManager like this:
MarkerManager markerManager = new MarkerManager(mMap);
mClusterManager1 = new ClusterManager<>(getContext(), mMap,markerManager);
mClusterManager2 = new ClusterManager<>(getContext(), mMap,markerManager);
mMap.setOnMarkerClickListener(markerManager);
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
mClusterManager1.onCameraChange(cameraPosition);
mClusterManager2.onCameraChange(cameraPosition);
}
});
mClusterManager1.setRenderer(myClusterRenderer1 = new MyClusterRenderer(getContext(), mMap, mClusterManager1));
mClusterManager2.setRenderer(myClusterRenderer2 = new MyClusterRenderer(getContext(), mMap, mClusterManager2));
Upvotes: 16
Reputation: 101
yes, delegate the click listener through to both cluster managers.
map.setOnClickListener(new GoogleMap.OnMarkerClickListener() {
boolean onMarkerClick(Marker m) {
clusterManager1.onMarkerClick(m)
clusterManager2.onMarkerClick(m)
}
});
Upvotes: 10