Android Maps Utils Clustering mostrar InfoWindow

Estoy planeando usar la agrupación de marcadores de google maps disponible en la biblioteca de utils, pero la aplicación de ejemplo de google solo muestra grupos de marcadores sin ninguna ventana de información. Me pregunto ahora, ¿no puedo mostrar InfoWindow? Quiero que InfoWindow se muestre en el marcador como con un marcador normal de Google Maps, no en el clúster.

El código que tengo: (Del ejemplo de google)

public class BigClusteringDemoActivity extends FragmentActivity { private ClusterManager mClusterManager; private GoogleMap mMap; private void readItems() { InputStream inputStream = getResources().openRawResource(R.raw.radar_search); List items = new MyItemReader().read(inputStream); for (int i = 0; i < 10; i++) { double offset = i / 60d; for (MyItem item : items) { LatLng position = item.getPosition(); double lat = position.latitude + offset; double lng = position.longitude + offset; MyItem offsetItem = new MyItem(lat, lng); mClusterManager.addItem(offsetItem); } } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); mClusterManager = new ClusterManager(this, mMap); mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); mMap.setOnCameraChangeListener(mClusterManager); readItems(); } } 

Aquí hay una solución simplificada y ligeramente modificada basada en esta respuesta . Tenga en cuenta que la respuesta vinculada implementa una ventana de información para marcadores y clústeres.

Esta solución solo implementa InfoWindows para marcadores.

Es similar a cómo implementaría un InfoWindowAdapter personalizado para marcadores normales sin clústeres, pero con el requisito adicional de que mantenga una referencia al elemento seleccionado actualmente para que pueda obtener el título y el MyItem instancia de MyItem , ya que el marcador lo hace no almacena el Título y el Fragmento como suele hacerlo.

Tenga en cuenta que dado que todos los datos se almacenan en referencias de MyItem , es mucho más fácil ampliar la funcionalidad para mostrar todos los tipos de datos que desee en InfoWindow para cada Marker.

Primero, MyItem.java, que incluye campos adicionales para Title and Snippet:

 public class MyItem implements ClusterItem { private final LatLng mPosition; private final String mTitle; private final String mSnippet; public MyItem(double lat, double lng, String t, String s) { mPosition = new LatLng(lat, lng); mTitle = t; mSnippet = s; } @Override public LatLng getPosition() { return mPosition; } public String getTitle(){ return mTitle; } public String getSnippet(){ return mSnippet; } } 

Aquí está la clase de actividad completa, que incluye toda la funcionalidad para admitir InfoWindows para cada marcador agregado con la biblioteca del clúster:

Editar: se agregó compatibilidad para manejar eventos de clic en InfoWindow, hizo que la actividad implementara OnClusterItemInfoWindowClickListener y agregó la onClusterItemInfoWindowClick llamada onClusterItemInfoWindowClick .

 public class MapsActivity extends AppCompatActivity implements ClusterManager.OnClusterItemInfoWindowClickListener { private ClusterManager mClusterManager; private MyItem clickedClusterItem; private GoogleMap mMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); setUpMapIfNeeded(); } @Override protected void onResume() { super.onResume(); setUpMapIfNeeded(); } private void setUpMapIfNeeded() { // Do a null check to confirm that we have not already instantiated the map. if (mMap == null) { // Try to obtain the map from the SupportMapFragment. mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)) .getMap(); // Check if we were successful in obtaining the map. if (mMap != null) { setUpMap(); } } } private void setUpMap() { mMap.getUiSettings().setMapToolbarEnabled(true); mMap.getUiSettings().setZoomControlsEnabled(true); mMap.setMyLocationEnabled(true); mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); mClusterManager = new ClusterManager<>(this, mMap); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.779977,-122.413742), 10)); mMap.setOnCameraChangeListener(mClusterManager); mMap.setOnMarkerClickListener(mClusterManager); mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager()); mMap.setOnInfoWindowClickListener(mClusterManager); //added mClusterManager.setOnClusterItemInfoWindowClickListener(this); //added mClusterManager .setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener() { @Override public boolean onClusterItemClick(MyItem item) { clickedClusterItem = item; return false; } }); addItems(); mClusterManager.getMarkerCollection().setOnInfoWindowAdapter( new MyCustomAdapterForItems()); } private void addItems() { double latitude = 37.779977; double longitude = -122.413742; for (int i = 0; i < 10; i++) { double offset = i / 60d; double lat = latitude + offset; double lng = longitude + offset; MyItem offsetItem = new MyItem(lat, lng, "title " + i+1, "snippet " + i+1); mClusterManager.addItem(offsetItem); } } //added with edit @Override public void onClusterItemInfoWindowClick(MyItem myItem) { //Cluster item InfoWindow clicked, set title as action Intent i = new Intent(this, OtherActivity.class); i.setAction(myItem.getTitle()); startActivity(i); //You may want to do different things for each InfoWindow: if (myItem.getTitle().equals("some title")){ //do something specific to this InfoWindow.... } } public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter { private final View myContentsView; MyCustomAdapterForItems() { myContentsView = getLayoutInflater().inflate( R.layout.info_window, null); } @Override public View getInfoWindow(Marker marker) { TextView tvTitle = ((TextView) myContentsView .findViewById(R.id.txtTitle)); TextView tvSnippet = ((TextView) myContentsView .findViewById(R.id.txtSnippet)); tvTitle.setText(clickedClusterItem.getTitle()); tvSnippet.setText(clickedClusterItem.getSnippet()); return myContentsView; } @Override public View getInfoContents(Marker marker) { return null; } } } 

info_window.xml:

      

Resultado:

Lanzamiento inicial:

enter image description here

Alejamiento, comienza la Agrupación:

enter image description here

Saliendo de nuevo, más Clustering:

enter image description here

A continuación, amplíe y haga clic en un marcador individual:

enter image description here

Luego, haciendo clic en otro marcador:

enter image description here

Editar: para mostrar el "bocadillo de diálogo" alrededor de la Ventana de información personalizada, use getInfoContents() lugar de getInfoWindow() :

 public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter { private final View myContentsView; MyCustomAdapterForItems() { myContentsView = getLayoutInflater().inflate( R.layout.info_window, null); } @Override public View getInfoWindow(Marker marker) { return null; } @Override public View getInfoContents(Marker marker) { TextView tvTitle = ((TextView) myContentsView .findViewById(R.id.txtTitle)); TextView tvSnippet = ((TextView) myContentsView .findViewById(R.id.txtSnippet)); tvTitle.setText(clickedClusterItem.getTitle()); tvSnippet.setText(clickedClusterItem.getSnippet()); return myContentsView; } } 

Resultado:

enter image description here

  @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map); mClusterManager = new ClusterManager<>(this, mMap); mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); mMap.setOnCameraChangeListener(mClusterManager); mMap.setInfoWindowAdapter(new InfoWindowAdapter() { /** * View for displaying marker popup, if null default framework view would be used */ @Override public View getInfoWindow(Marker marker) { return null; } /** * For changing the content of infowindow * Called when showMarkerInfo method is called */ @Override public View getInfoContents(Marker marker) { View v = getLayoutInflater().inflate(R.layout.view_to_inflate, null); //code for initializing view part return v; } }); readItems(); } 

Podría considerar el siguiente enfoque:

 public void initilizeMap() { googleMap = mFragment.getMap(); googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN); googleMap.getUiSettings().setZoomControlsEnabled(true`enter code here`); // true to`enter code here` googleMap.getUiSettings().setZoomGesturesEnabled(true); googleMap.getUiSettings().setCompassEnabled(true); googleMap.getUiSettings().setMyLocationButtonEnabled(true); googleMap.getUiSettings().setRotateGesturesEnabled(true); if (googleMap == null) { Toast.makeText(getActivity(), "Sorry! unable to create maps", Toast.LENGTH_SHORT).show(); } mClusterManager = new ClusterManager(getActivity(), googleMap ); // googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter()); googleMap.setOnMapLoadedCallback(this); googleMap.setMyLocationEnabled(true); googleMap.setBuildingsEnabled(true); googleMap.getUiSettings().setTiltGesturesEnabled(true); MyItem offsetItem = new MyItem(Double.parseDouble(outletList.get(i).getMap_latitude()), Double.parseDouble(outletList.get(i).getMap_longitude()), title , address); mClusterManager.addItem(offsetItem); googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(offsetItem)); } private class CustomInfoWindowAdapter implements InfoWindowAdapter { Marker marker; private View view; private MyItem items; public CustomInfoWindowAdapter(MyItem item) { view = getActivity().getLayoutInflater().inflate( R.layout.custom_info_window, null); this.items = item; } @Override public View getInfoContents(Marker marker) { if (marker != null && marker.isInfoWindowShown()) { marker.hideInfoWindow(); marker.showInfoWindow(); } return null; } @Override public View getInfoWindow(final Marker marker) { this.marker = marker; String url = null; if (marker.getId() != null && markers != null && markers.size() > 0) { if (markers.get(marker.getId()) != null && markers.get(marker.getId()) != null) { url = markers.get(marker.getId()); } } final ImageView image = ((ImageView) view.findViewById(R.id.badge)); if (url != null && !url.equalsIgnoreCase("null") && !url.equalsIgnoreCase("")) { imageLoader.displayImage(url, image, options, new SimpleImageLoadingListener() { @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { super.onLoadingComplete(imageUri, view, loadedImage); getInfoContents(marker); } }); } else { image.setImageResource(R.drawable.ic_launcher); } final String title = items.getTitle(); Log.e(TAG, "TITLE : "+title); final TextView titleUi = ((TextView) view.findViewById(R.id.title)); if (title != null) { titleUi.setText(title); } else { titleUi.setText(""); } final String address = items.getAddress(); final TextView snippetUi = ((TextView) view .findViewById(R.id.snippet)); if (address != null) { snippetUi.setText(address); } else { snippetUi.setText(""); }