Cuando agrupas tus marcadores en clústeres, puedes incluir muchos marcadores en un mapa sin que esto dificulte su lectura.
Introducción
En este video, se trata el uso del agrupamiento de marcadores en clústeres cuando tus datos requieren una gran cantidad de puntos de datos en el mapa.
La utilidad del agrupamiento de marcadores en clústeres te permite administrar varios marcadores con diferentes niveles de zoom. Para ser precisos, los "marcadores" en realidad son "elementos" en este punto y solo se convierten en "marcadores" al renderizarse. No obstante, a fin de garantizar una mayor claridad, se usará la denominación "marcador" en todo el documento.
Cuando un usuario visualiza el mapa con un alto nivel de zoom, aparecen los marcadores individuales. Cuando el usuario aleja el mapa, los marcadores se agrupan en clústeres para facilitar su visualización. La utilidad del agrupamiento de marcadores en clústeres forma parte de la biblioteca de utilidades del SDK de Maps para Android. Si aún no configuraste la biblioteca, sigue la guía de configuración antes de leer el resto de esta página.
Para usar la utilidad del agrupamiento de marcadores en clústeres, deberás agregar marcadores como objetos ClusterItem
a ClusterManager
. ClusterManager
pasa los marcadores a Algorithm
y este los transforma en un conjunto de clústeres. ClusterRenderer
se encarga de la renderización. Para hacerlo, agrega y quita clústeres y marcadores individuales. ClusterRenderer
y Algorithm
son acoplables y se pueden personalizar.
En la biblioteca de utilidades se incluye una app de demostración en la que se ofrecen ejemplos de implementaciones de la utilidad de agrupamiento de marcadores en clústeres. Para obtener ayuda con la ejecución de la app de demostración, consulta la guía de configuración. En la app de demostración se incluyen los siguientes ejemplos de agrupamientos de marcadores en clústeres:
ClusteringDemoActivity
: una actividad simple en la que se muestra el agrupamiento de marcadores en clústeresBigClusteringDemoActivity
: agrupamiento en clústeres de 2,000 marcadoresCustomMarkerClusteringDemoActivity
: creación de un diseño personalizado para los marcadores agrupados en clústeres
Cómo agregar un agrupador de marcadores en clústeres simple
Sigue los pasos que aparecen a continuación para crear un clúster simple de diez marcadores. El resultado tendrá el siguiente aspecto, aunque el número de marcadores que se muestren o aparezcan agrupados en clúster cambiará según el nivel de zoom:
A continuación, se ofrece un resumen de los pasos que deben seguirse:
- Implementa
ClusterItem
para representar un marcador en el mapa. El elemento de clúster muestra la posición del marcador como un objeto LatLng y un título o un fragmento opcionales. - Agrega un objeto
ClusterManager
nuevo para agrupar los elementos del clúster (marcadores) en función del nivel de zoom. - Configura el método
OnCameraIdleListener()
del mapa enClusterManager
, ya queClusterManager
implementa el objeto de escucha. - Si deseas agregar funcionalidades específicas en respuesta a un evento de clic de marcador, configura el método
OnMarkerClickListener()
del mapa enClusterManager
, ya queClusterManager
implementa el objeto de escucha. - Ingresa los marcadores en
ClusterManager
.
Una vista detallada de los pasos: para crear el clúster simple de diez marcadores, primero crea una clase MyItem
con la que se implemente ClusterItem
.
Kotlin
inner class MyItem( lat: Double, lng: Double, title: String, snippet: String ) : ClusterItem { private val position: LatLng private val title: String private val snippet: String override fun getPosition(): LatLng { return position } override fun getTitle(): String { return title } override fun getSnippet(): String { return snippet } override fun getZIndex(): Float { return 0f } init { position = LatLng(lat, lng) this.title = title this.snippet = snippet } }
Java
public class MyItem implements ClusterItem { private final LatLng position; private final String title; private final String snippet; public MyItem(double lat, double lng, String title, String snippet) { position = new LatLng(lat, lng); this.title = title; this.snippet = snippet; } @Override public LatLng getPosition() { return position; } @Override public String getTitle() { return title; } @Override public String getSnippet() { return snippet; } @Nullable @Override public Float getZIndex() { return 0f; } }
En tu actividad en Maps, agrega ClusterManager
y transmítele los elementos del clúster. Considera el argumento de tipo <MyItem>
, que declara que ClusterManager
corresponde al tipo MyItem
.
Kotlin
// Declare a variable for the cluster manager. private lateinit var clusterManager: ClusterManager<MyItem> private fun setUpClusterer() { // Position the map. map.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.503186, -0.126446), 10f)) // Initialize the manager with the context and the map. // (Activity extends context, so we can pass 'this' in the constructor.) clusterManager = ClusterManager(context, map) // Point the map's listeners at the listeners implemented by the cluster // manager. map.setOnCameraIdleListener(clusterManager) map.setOnMarkerClickListener(clusterManager) // Add cluster items (markers) to the cluster manager. addItems() } private fun addItems() { // Set some lat/lng coordinates to start with. var lat = 51.5145160 var lng = -0.1270060 // Add ten cluster items in close proximity, for purposes of this example. for (i in 0..9) { val offset = i / 60.0 lat += offset lng += offset val offsetItem = MyItem(lat, lng, "Title $i", "Snippet $i") clusterManager.addItem(offsetItem) } }
Java
// Declare a variable for the cluster manager. private ClusterManager<MyItem> clusterManager; private void setUpClusterer() { // Position the map. map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); // Initialize the manager with the context and the map. // (Activity extends context, so we can pass 'this' in the constructor.) clusterManager = new ClusterManager<MyItem>(context, map); // Point the map's listeners at the listeners implemented by the cluster // manager. map.setOnCameraIdleListener(clusterManager); map.setOnMarkerClickListener(clusterManager); // Add cluster items (markers) to the cluster manager. addItems(); } private void addItems() { // Set some lat/lng coordinates to start with. double lat = 51.5145160; double lng = -0.1270060; // Add ten cluster items in close proximity, for purposes of this example. for (int i = 0; i < 10; i++) { double offset = i / 60d; lat = lat + offset; lng = lng + offset; MyItem offsetItem = new MyItem(lat, lng, "Title " + i, "Snippet " + i); clusterManager.addItem(offsetItem); } }
También puedes inhabilitar las animaciones de agrupamiento en clústeres cuando acercas o alejas el mapa.
Si la animación está desactivada, los marcadores se ubican en su posición en lugar de migrar desde y hacia los clústeres.
Para inhabilitar las animaciones, usa setAnimation()
en ClusterManager
como se muestra a continuación:
Kotlin
clusterManager.setAnimation(false)
Java
clusterManager.setAnimation(false);
Cómo agregar una ventana de información para un marcador agrupado en clúster individual
A fin de agregar una ventana de información para marcadores agrupados en clústeres específicos, agrega strings de título y fragmento al constructor de tu implementación de ClusterItem
.
En el siguiente ejemplo, se configura un título y un fragmento para agregar un marcador con una ventana de información en el método addItems()
:
Kotlin
// Set the lat/long coordinates for the marker. val lat = 51.5009 val lng = -0.122 // Set the title and snippet strings. val title = "This is the title" val snippet = "and this is the snippet." // Create a cluster item for the marker and set the title and snippet using the constructor. val infoWindowItem = MyItem(lat, lng, title, snippet) // Add the cluster item (marker) to the cluster manager. clusterManager.addItem(infoWindowItem)
Java
// Set the lat/long coordinates for the marker. double lat = 51.5009; double lng = -0.122; // Set the title and snippet strings. String title = "This is the title"; String snippet = "and this is the snippet."; // Create a cluster item for the marker and set the title and snippet using the constructor. MyItem infoWindowItem = new MyItem(lat, lng, title, snippet); // Add the cluster item (marker) to the cluster manager. clusterManager.addItem(infoWindowItem);
Cómo personalizar los clústeres de marcadores
El constructor de ClusterManager
crea DefaultClusterRenderer
y NonHierarchicalDistanceBasedAlgorithm
. Puedes cambiar ClusterRenderer
y Algorithm
con los métodos setAlgorithm(Algorithm<T> algorithm)
y setRenderer(ClusterRenderer<T> view)
de ClusterManager
.
Puedes implementar ClusterRenderer
para personalizar la renderización de los clústeres. DefaultClusterRenderer
proporciona una buena base como punto de partida. Puedes subclasificar DefaultClusterRenderer
para anular los valores predeterminados.
Para ver un ejemplo exhaustivo de la personalización, consulta CustomMarkerClusteringDemoActivity
en la app de demostración que se incluye en la biblioteca de utilidades.
CustomMarkerClusteringDemoActivity
define su propio elemento de clúster, Person
, y lo renderiza extendiendo DefaultClusterRenderer
como PersonRenderer
.
La demostración también muestra cómo implementar la interfaz ClusterManager.OnClusterClickListener<Person>
para mostrar más información sobre la persona cuando se hace clic en el clúster. También puedes implementar ClusterManager.OnClusterItemClickListener<Person>
de manera similar.
Para obtener ayuda con la ejecución de la app de demostración, consulta la guía de configuración.